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