Skip to content

Commit ae93ee3

Browse files
committedJun 15, 2016
Use QgsFieldProxyModel for filtering read only fields
1 parent 8563285 commit ae93ee3

9 files changed

+76
-86
lines changed
 

‎python/gui/qgsfieldmodel.sip

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,9 @@ class QgsFieldModel : QAbstractItemModel
1919
ExpressionRole, /*!< return field name or expression */
2020
IsExpressionRole, /*!< return if index corresponds to an expression */
2121
ExpressionValidityRole, /*!< return if expression is valid or not */
22-
FieldTypeRole /*!< return the field type (if a field, return QVariant if expression) */
22+
FieldTypeRole, /*!< return the field type (if a field, return QVariant if expression) */
23+
FieldOriginRole, /*!< return the field origin (if a field, returns QVariant if expression) */
2324
};
24-
/**
25-
* Filters for which fields should be shown
26-
*/
27-
enum Filter
28-
{
29-
WritableFields = 1 //!< Only show writable fields
30-
};
31-
typedef QFlags<QgsFieldModel::Filter> Filters;
3225

3326
/**
3427
* @brief QgsFieldModel creates a model to display the fields of a given layer
@@ -54,15 +47,6 @@ class QgsFieldModel : QAbstractItemModel
5447

5548
//! returns the currently used layer
5649
QgsVectorLayer* layer();
57-
/**
58-
* The currently applied filters that define which fields are shown.
59-
*/
60-
Filters filters() const;
61-
62-
/**
63-
* The currently applied filters that define which fields are shown.
64-
*/
65-
void setFilters( const Filters& filter );
6650

6751
public slots:
6852
//! set the layer of whch fields are displayed

‎python/gui/qgsfieldproxymodel.sip

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ class QgsFieldProxyModel : QSortFilterProxyModel
2121
Numeric, /*!< All numeric fields */
2222
Date, /*!< Date or datetime fields */
2323
Time, /*!< Time fields */
24-
All, /*!< All fields */
24+
HideReadOnly, /*!< Hide read-only fields */
25+
All, /*!< All field types */
2526
};
2627
typedef QFlags<QgsFieldProxyModel::Filter> Filters;
2728

‎src/app/qgsattributetabledialog.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "qgsrubberband.h"
4848
#include "qgsfield.h"
4949
#include "qgseditorwidgetregistry.h"
50+
#include "qgsfieldproxymodel.h"
5051

5152
static QgsExpressionContext _getExpressionContext( const void* context )
5253
{
@@ -248,11 +249,9 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
248249
}
249250

250251
mUpdateExpressionText->registerGetExpressionContextCallback( &_getExpressionContext, mLayer );
252+
mFieldCombo->setFilters( QgsFieldProxyModel::All | QgsFieldProxyModel::HideReadOnly );
253+
mFieldCombo->setLayer( mLayer );
251254

252-
mFieldModel = new QgsFieldModel( this );
253-
mFieldModel->setFilters( QgsFieldModel::WritableFields );
254-
mFieldModel->setLayer( mLayer );
255-
mFieldCombo->setModel( mFieldModel );
256255
connect( mRunFieldCalc, SIGNAL( clicked() ), this, SLOT( updateFieldFromExpression() ) );
257256
connect( mRunFieldCalcSelected, SIGNAL( clicked() ), this, SLOT( updateFieldFromExpressionSelected() ) );
258257
// NW TODO Fix in 2.6 - Doesn't work with field model for some reason.
@@ -411,8 +410,7 @@ void QgsAttributeTableDialog::runFieldCalculation( QgsVectorLayer* layer, const
411410

412411
mLayer->beginEditCommand( "Field calculator" );
413412

414-
QModelIndex modelindex = mFieldModel->indexFromName( fieldName );
415-
int fieldindex = modelindex.data( QgsFieldModel::FieldIndexRole ).toInt();
413+
int fieldindex = layer->fields().indexFromName( fieldName );
416414

417415
bool calculationSuccess = true;
418416
QString error;
@@ -738,6 +736,10 @@ void QgsAttributeTableDialog::editingToggled()
738736
mAddFeature->setEnabled( canAddFeatures && mLayer->isEditable() );
739737

740738
mUpdateExpressionBox->setVisible( mLayer->isEditable() );
739+
if ( mLayer->isEditable() && mFieldCombo->currentIndex() == -1 )
740+
{
741+
mFieldCombo->setCurrentIndex( 0 );
742+
}
741743
// not necessary to set table read only if layer is not editable
742744
// because model always reflects actual state when returning item flags
743745
}

‎src/app/qgsattributetabledialog.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828

2929
#include "qgsattributedialog.h"
3030
#include "qgsvectorlayer.h" //QgsFeatureIds
31-
#include "qgsfieldmodel.h"
3231
#include "qgssearchwidgetwrapper.h"
3332
#include "qgsdockwidget.h"
3433

@@ -222,8 +221,6 @@ class APP_EXPORT QgsAttributeTableDialog : public QDialog, private Ui::QgsAttrib
222221
QSignalMapper* mFilterActionMapper;
223222

224223
QgsVectorLayer* mLayer;
225-
QgsFieldModel* mFieldModel;
226-
227224
QgsRubberBand* mRubberBand;
228225
QgsSearchWidgetWrapper* mCurrentSearchWidgetWrapper;
229226
QStringList mVisibleFields;

‎src/gui/qgsfieldmodel.cpp

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -94,35 +94,11 @@ void QgsFieldModel::layerDeleted()
9494
updateModel();
9595
}
9696

97-
QgsFieldModel::Filters QgsFieldModel::filters() const
98-
{
99-
return mFilters;
100-
}
101-
102-
void QgsFieldModel::setFilters( const Filters& filters )
103-
{
104-
if ( filters == mFilters )
105-
return;
106-
107-
mFilters = filters;
108-
109-
updateModel();
110-
}
111-
11297
void QgsFieldModel::updateModel()
11398
{
11499
if ( mLayer )
115100
{
116-
QgsFields fields = mLayer->fields();
117-
QgsFields newFields;
118-
for ( int i = 0; i < fields.count(); ++i )
119-
{
120-
if ( fields.fieldOrigin( i ) != QgsFields::OriginExpression && fields.fieldOrigin( i ) != QgsFields::OriginJoin )
121-
{
122-
newFields.append( fields.at( i ), fields.fieldOrigin( i ), fields.fieldOriginIndex( i ) );
123-
}
124-
}
125-
101+
QgsFields newFields = mLayer->fields();
126102
if ( mFields.toList() != newFields.toList() )
127103
{
128104
// Try to handle two special cases: addition of a new field and removal of a field.
@@ -277,19 +253,19 @@ QVariant QgsFieldModel::data( const QModelIndex &index, int role ) const
277253
{
278254
return "";
279255
}
280-
QgsField field = mFields[index.row()];
256+
QgsField field = mFields.at( index.row() );
281257
return field.name();
282258
}
283259

284260
case ExpressionRole:
285261
{
286262
if ( exprIdx >= 0 )
287263
{
288-
return mExpression[exprIdx];
264+
return mExpression.at( exprIdx );
289265
}
290266
else
291267
{
292-
QgsField field = mFields[index.row()];
268+
QgsField field = mFields.at( index.row() );
293269
return field.name();
294270
}
295271
}
@@ -312,7 +288,7 @@ QVariant QgsFieldModel::data( const QModelIndex &index, int role ) const
312288
{
313289
if ( exprIdx >= 0 )
314290
{
315-
QgsExpression exp( mExpression[exprIdx] );
291+
QgsExpression exp( mExpression.at( exprIdx ) );
316292
QgsExpressionContext context;
317293
if ( mLayer )
318294
context.setFields( mLayer->fields() );
@@ -327,22 +303,31 @@ QVariant QgsFieldModel::data( const QModelIndex &index, int role ) const
327303
{
328304
if ( exprIdx < 0 )
329305
{
330-
QgsField field = mFields[index.row()];
306+
QgsField field = mFields.at( index.row() );
331307
return static_cast< int >( field.type() );
332308
}
333309
return QVariant();
334310
}
335311

312+
case FieldOriginRole:
313+
{
314+
if ( exprIdx < 0 )
315+
{
316+
return static_cast< int >( mFields.fieldOrigin( index.row() ) );
317+
}
318+
return QVariant();
319+
}
320+
336321
case Qt::DisplayRole:
337322
case Qt::EditRole:
338323
{
339324
if ( exprIdx >= 0 )
340325
{
341-
return mExpression[exprIdx];
326+
return mExpression.at( exprIdx );
342327
}
343328
else if ( role == Qt::EditRole )
344329
{
345-
return mFields[index.row()].name();
330+
return mFields.at( index.row() ).name();
346331
}
347332
else if ( mLayer )
348333
{
@@ -357,7 +342,7 @@ QVariant QgsFieldModel::data( const QModelIndex &index, int role ) const
357342
if ( exprIdx >= 0 )
358343
{
359344
// if expression, test validity
360-
QgsExpression exp( mExpression[exprIdx] );
345+
QgsExpression exp( mExpression.at( exprIdx ) );
361346
QgsExpressionContext context;
362347
if ( mLayer )
363348
context.setFields( mLayer->fields() );

‎src/gui/qgsfieldmodel.h

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,10 @@ class GUI_EXPORT QgsFieldModel : public QAbstractItemModel
3939
ExpressionRole = Qt::UserRole + 3, /*!< return field name or expression */
4040
IsExpressionRole = Qt::UserRole + 4, /*!< return if index corresponds to an expression */
4141
ExpressionValidityRole = Qt::UserRole + 5, /*!< return if expression is valid or not */
42-
FieldTypeRole = Qt::UserRole + 6 /*!< return the field type (if a field, return QVariant if expression) */
42+
FieldTypeRole = Qt::UserRole + 6, /*!< return the field type (if a field, return QVariant if expression) */
43+
FieldOriginRole = Qt::UserRole + 7, /*!< return the field origin (if a field, returns QVariant if expression) */
4344
};
4445

45-
/**
46-
* Filters for which fields should be shown
47-
*/
48-
enum Filter
49-
{
50-
WritableFields = 1 //!< Only show writable fields
51-
};
52-
Q_DECLARE_FLAGS( Filters, Filter )
53-
5446
/**
5547
* @brief QgsFieldModel creates a model to display the fields of a given layer
5648
*/
@@ -83,16 +75,6 @@ class GUI_EXPORT QgsFieldModel : public QAbstractItemModel
8375
int columnCount( const QModelIndex &parent ) const override;
8476
QVariant data( const QModelIndex &index, int role ) const override;
8577

86-
/**
87-
* The currently applied filters that define which fields are shown.
88-
*/
89-
Filters filters() const;
90-
91-
/**
92-
* The currently applied filters that define which fields are shown.
93-
*/
94-
void setFilters( const Filters& filter );
95-
9678
public slots:
9779
//! set the layer of whch fields are displayed
9880
void setLayer( QgsVectorLayer *layer );
@@ -103,14 +85,14 @@ class GUI_EXPORT QgsFieldModel : public QAbstractItemModel
10385
private slots:
10486
void layerDeleted();
10587

106-
private:
88+
protected:
10789
QgsFields mFields;
10890
QList<QString> mExpression;
10991

11092
QgsVectorLayer* mLayer;
11193
bool mAllowExpression;
112-
Filters mFilters;
11394

95+
private:
11496
void fetchFeature();
11597
};
11698

‎src/gui/qgsfieldproxymodel.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,42 @@ QgsFieldProxyModel *QgsFieldProxyModel::setFilters( const Filters& filters )
3232
return this;
3333
}
3434

35+
bool QgsFieldProxyModel::isReadOnly( const QModelIndex& index ) const
36+
{
37+
QVariant originVariant = sourceModel()->data( index, QgsFieldModel::FieldOriginRole );
38+
if ( originVariant.isNull() )
39+
{
40+
//expression
41+
return true;
42+
}
43+
44+
QgsFields::FieldOrigin origin = static_cast< QgsFields::FieldOrigin >( originVariant.toInt() );
45+
switch ( origin )
46+
{
47+
case QgsFields::OriginUnknown:
48+
case QgsFields::OriginJoin:
49+
case QgsFields::OriginExpression:
50+
//read only
51+
return true;
52+
53+
case QgsFields::OriginEdit:
54+
case QgsFields::OriginProvider:
55+
//not read only
56+
return false;
57+
}
58+
return false; // avoid warnings
59+
}
60+
3561
bool QgsFieldProxyModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const
3662
{
63+
QModelIndex index = sourceModel()->index( source_row, 0, source_parent );
64+
65+
if ( mFilters.testFlag( HideReadOnly ) && isReadOnly( index ) )
66+
return false;
67+
3768
if ( mFilters.testFlag( All ) )
3869
return true;
3970

40-
QModelIndex index = sourceModel()->index( source_row, 0, source_parent );
4171
QVariant typeVar = sourceModel()->data( index, QgsFieldModel::FieldTypeRole );
4272

4373
// if expression, consider valid

‎src/gui/qgsfieldproxymodel.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ class GUI_EXPORT QgsFieldProxyModel : public QSortFilterProxyModel
4141
Numeric = Int | LongLong | Double, /*!< All numeric fields */
4242
Date = 16, /*!< Date or datetime fields */
4343
Time = 32, /*!< Time fields */
44-
All = Numeric | Date | String | Time, /*!< All fields */
44+
HideReadOnly = 64, /*!< Hide read-only fields */
45+
All = Numeric | Date | String | Time, /*!< All field types */ //TODO QGIS 3 - rename to AllTypes
4546
};
4647
Q_DECLARE_FLAGS( Filters, Filter )
4748

@@ -70,6 +71,9 @@ class GUI_EXPORT QgsFieldProxyModel : public QSortFilterProxyModel
7071
Filters mFilters;
7172
QgsFieldModel* mModel;
7273

74+
//! Returns true if the specified index represents a read only field
75+
bool isReadOnly( const QModelIndex& index ) const;
76+
7377
// QSortFilterProxyModel interface
7478
public:
7579
bool filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const override;

‎src/ui/qgsattributetabledialog.ui

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,7 @@
787787
<number>3</number>
788788
</property>
789789
<item>
790-
<widget class="QComboBox" name="mFieldCombo"/>
790+
<widget class="QgsFieldComboBox" name="mFieldCombo"/>
791791
</item>
792792
<item>
793793
<widget class="QLabel" name="label">
@@ -910,6 +910,11 @@
910910
<header>qgsdualview.h</header>
911911
<container>1</container>
912912
</customwidget>
913+
<customwidget>
914+
<class>QgsFieldComboBox</class>
915+
<extends>QComboBox</extends>
916+
<header>qgsfieldcombobox.h</header>
917+
</customwidget>
913918
</customwidgets>
914919
<tabstops>
915920
<tabstop>mToggleEditingButton</tabstop>

0 commit comments

Comments
 (0)
Please sign in to comment.