1 /***************************************************************************
2 qgsfieldproxymodel.cpp
3 --------------------------------------
4 Date : 01.04.2014
5 Copyright : (C) 2014 Denis Rouzaud
6 Email : denis.rouzaud@gmail.com
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 "qgsvectorlayer.h"
19
QgsFieldProxyModel(QObject * parent)20 QgsFieldProxyModel::QgsFieldProxyModel( QObject *parent )
21 : QSortFilterProxyModel( parent )
22 , mFilters( AllTypes )
23 , mModel( new QgsFieldModel( this ) )
24 {
25 setSourceModel( mModel );
26 }
27
setFilters(QgsFieldProxyModel::Filters filters)28 QgsFieldProxyModel *QgsFieldProxyModel::setFilters( QgsFieldProxyModel::Filters filters )
29 {
30 mFilters = filters;
31 invalidateFilter();
32 return this;
33 }
34
isReadOnly(const QModelIndex & index) const35 bool QgsFieldProxyModel::isReadOnly( const QModelIndex &index ) const
36 {
37 const QVariant originVariant = sourceModel()->data( index, QgsFieldModel::FieldOriginRole );
38 if ( originVariant.isNull() )
39 {
40 //expression
41 return true;
42 }
43
44 const QgsFields::FieldOrigin origin = static_cast< QgsFields::FieldOrigin >( originVariant.toInt() );
45 switch ( origin )
46 {
47 case QgsFields::OriginJoin:
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, QgsFieldModel::EditorWidgetType ).toString() == QLatin1String( "Hidden" ) )
53 return true;
54
55 return !sourceModel()->data( index, QgsFieldModel::JoinedFieldIsEditable ).toBool();
56 }
57
58 case QgsFields::OriginUnknown:
59 case QgsFields::OriginExpression:
60 //read only
61 return true;
62
63 case QgsFields::OriginEdit:
64 case QgsFields::OriginProvider:
65 {
66 if ( !sourceModel()->data( index, QgsFieldModel::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
filterAcceptsRow(int source_row,const QModelIndex & source_parent) const81 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( AllTypes ) )
89 return true;
90
91 const QVariant typeVar = sourceModel()->data( index, QgsFieldModel::FieldTypeRole );
92
93 // if expression, consider valid
94 if ( typeVar.isNull() )
95 return true;
96
97 bool ok;
98 const QVariant::Type type = ( QVariant::Type )typeVar.toInt( &ok );
99 if ( !ok )
100 return true;
101
102 if ( ( mFilters.testFlag( String ) && type == QVariant::String ) ||
103 ( mFilters.testFlag( LongLong ) && type == QVariant::LongLong ) ||
104 ( mFilters.testFlag( Int ) && type == QVariant::Int ) ||
105 ( mFilters.testFlag( Double ) && type == QVariant::Double ) ||
106 ( mFilters.testFlag( Date ) && type == QVariant::Date ) ||
107 ( mFilters.testFlag( Date ) && type == QVariant::DateTime ) ||
108 ( mFilters.testFlag( DateTime ) && type == QVariant::DateTime ) ||
109 ( mFilters.testFlag( Time ) && type == QVariant::Time ) )
110 return true;
111
112 return false;
113 }
114
lessThan(const QModelIndex & left,const QModelIndex & right) const115 bool QgsFieldProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
116 {
117 // empty field is always first
118 if ( sourceModel()->data( left, QgsFieldModel::IsEmptyRole ).toBool() )
119 return true;
120 else if ( sourceModel()->data( right, QgsFieldModel::IsEmptyRole ).toBool() )
121 return false;
122
123 // order is field order, then expressions
124 bool lok, rok;
125 const int leftId = sourceModel()->data( left, QgsFieldModel::FieldIndexRole ).toInt( &lok );
126 const int rightId = sourceModel()->data( right, QgsFieldModel::FieldIndexRole ).toInt( &rok );
127
128 if ( !lok )
129 return false;
130 if ( !rok )
131 return true;
132
133 return leftId < rightId;
134 }
135