QGIS API Documentation  3.37.0-Master (a5b4d9743e8)
qgsfieldproxymodel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfieldproxymodel.cpp
3  --------------------------------------
4  Date : 01.04.2014
5  Copyright : (C) 2014 Denis Rouzaud
6  Email : [email protected]
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15 
16 #include "qgsfieldproxymodel.h"
17 #include "qgsfieldmodel.h"
18 #include "qgsvariantutils.h"
19 
21  : QSortFilterProxyModel( parent )
22  , mFilters( AllTypes )
23  , mModel( new QgsFieldModel( this ) )
24 {
25  setSourceModel( mModel );
26 }
27 
29 {
30  mFilters = filters;
31  invalidateFilter();
32  return this;
33 }
34 
35 bool QgsFieldProxyModel::isReadOnly( const QModelIndex &index ) const
36 {
37  const QVariant originVariant = sourceModel()->data( index, static_cast< int >( QgsFieldModel::CustomRole::FieldOrigin ) );
38  if ( QgsVariantUtils::isNull( originVariant ) )
39  {
40  //expression
41  return true;
42  }
43 
44  const QgsFields::FieldOrigin origin = static_cast< QgsFields::FieldOrigin >( originVariant.toInt() );
45  switch ( origin )
46  {
48  {
49  // show joined fields (e.g. auxiliary fields) only if they have a non-hidden editor widget.
50  // This enables them to be bulk field-calculated when a user needs to, but hides them by default
51  // (since there's often MANY of these, e.g. after using the label properties tool on a layer)
52  if ( sourceModel()->data( index, static_cast< int >( QgsFieldModel::CustomRole::EditorWidgetType ) ).toString() == QLatin1String( "Hidden" ) )
53  return true;
54 
55  return !sourceModel()->data( index, static_cast< int >( QgsFieldModel::CustomRole::JoinedFieldIsEditable ) ).toBool();
56  }
57 
60  //read only
61  return true;
62 
65  {
66  if ( !sourceModel()->data( index, static_cast< int >( QgsFieldModel::CustomRole::FieldIsWidgetEditable ) ).toBool() )
67  {
68  return true;
69  }
70  else
71  {
72  //not read only
73  return false;
74  }
75  }
76 
77  }
78  return false; // avoid warnings
79 }
80 
81 bool QgsFieldProxyModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const
82 {
83  const QModelIndex index = sourceModel()->index( source_row, 0, source_parent );
84 
85  if ( mFilters.testFlag( HideReadOnly ) && isReadOnly( index ) )
86  return false;
87 
88  if ( mFilters.testFlag( QgsFieldProxyModel::OriginProvider ) )
89  {
90  const QgsFields::FieldOrigin origin = static_cast< QgsFields::FieldOrigin >( sourceModel()->data( index, static_cast< int >( QgsFieldModel::CustomRole::FieldOrigin ) ).toInt() );
91  switch ( origin )
92  {
97  return false;
98 
100  break;
101  }
102  }
103 
104  if ( mFilters.testFlag( AllTypes ) )
105  return true;
106 
107  const QVariant typeVar = sourceModel()->data( index, static_cast< int >( QgsFieldModel::CustomRole::FieldType ) );
108 
109  // if expression, consider valid
110  if ( QgsVariantUtils::isNull( typeVar ) )
111  return true;
112 
113  bool ok;
114  const QVariant::Type type = ( QVariant::Type )typeVar.toInt( &ok );
115  if ( !ok )
116  return true;
117 
118  if ( ( mFilters.testFlag( String ) && type == QVariant::String ) ||
119  ( mFilters.testFlag( LongLong ) && type == QVariant::LongLong ) ||
120  ( mFilters.testFlag( Int ) && type == QVariant::Int ) ||
121  ( mFilters.testFlag( Double ) && type == QVariant::Double ) ||
122  ( mFilters.testFlag( Date ) && type == QVariant::Date ) ||
123  ( mFilters.testFlag( Date ) && type == QVariant::DateTime ) ||
124  ( mFilters.testFlag( DateTime ) && type == QVariant::DateTime ) ||
125  ( mFilters.testFlag( Time ) && type == QVariant::Time ) ||
126  ( mFilters.testFlag( Binary ) && type == QVariant::ByteArray ) ||
127  ( mFilters.testFlag( Boolean ) && type == QVariant::Bool ) )
128  return true;
129 
130  return false;
131 }
132 
133 bool QgsFieldProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
134 {
135  // empty field is always first
136  if ( sourceModel()->data( left, static_cast< int >( QgsFieldModel::CustomRole::IsEmpty ) ).toBool() )
137  return true;
138  else if ( sourceModel()->data( right, static_cast< int >( QgsFieldModel::CustomRole::IsEmpty ) ).toBool() )
139  return false;
140 
141  // order is field order, then expressions
142  bool lok, rok;
143  const int leftId = sourceModel()->data( left, static_cast< int >( QgsFieldModel::CustomRole::FieldIndex ) ).toInt( &lok );
144  const int rightId = sourceModel()->data( right, static_cast< int >( QgsFieldModel::CustomRole::FieldIndex ) ).toInt( &rok );
145 
146  if ( !lok )
147  return false;
148  if ( !rok )
149  return true;
150 
151  return leftId < rightId;
152 }
The QgsFieldModel class is a model to display the list of fields in widgets (optionally associated wi...
Definition: qgsfieldmodel.h:38
@ FieldIsWidgetEditable
true if a is editable from the widget
@ FieldOrigin
Return the field origin (if a field, returns QVariant if expression)
@ IsEmpty
Return if the index corresponds to the empty value.
@ FieldIndex
Return field index if index corresponds to a field.
@ EditorWidgetType
Editor widget type.
@ FieldType
Return the field type (if a field, return QVariant if expression)
@ JoinedFieldIsEditable
true if a joined field is editable (returns QVariant if not a joined field)
The QgsFieldProxyModel class provides an easy to use model to display the list of fields of a layer.
const Filters & filters() const
Returns the filters controlling displayed fields.
@ DateTime
Datetime fields.
@ HideReadOnly
Hide read-only fields.
@ LongLong
Longlong fields.
@ Double
Double fields.
@ AllTypes
All field types.
@ Date
Date or datetime fields.
@ Binary
Binary fields, since QGIS 3.34.
@ Int
Integer fields.
@ String
String fields.
@ Boolean
Boolean fields, since QGIS 3.34.
@ OriginProvider
Fields with a provider origin, since QGIS 3.38.
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
QgsFieldProxyModel(QObject *parent=nullptr)
QgsFieldProxModel creates a proxy model with a QgsFieldModel as source model.
QFlags< Filter > Filters
QgsFieldProxyModel * setFilters(QgsFieldProxyModel::Filters filters)
Set flags that affect how fields are filtered in the model.
@ OriginExpression
Field is calculated from an expression.
Definition: qgsfields.h:54
@ OriginEdit
Field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfields.h:53
@ OriginUnknown
It has not been specified where the field comes from.
Definition: qgsfields.h:50
@ OriginJoin
Field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfields.h:52
@ OriginProvider
Field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
Definition: qgsfields.h:51
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.