1 /***************************************************************************
2     qgsfeaturelistmodel.h
3     ---------------------
4     begin                : February 2013
5     copyright            : (C) 2013 by Matthias Kuhn
6     email                : matthias at opengis dot ch
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 #ifndef QGSATTRIBUTEEDITORMODEL_H
16 #define QGSATTRIBUTEEDITORMODEL_H
17 
18 #include "qgsexpression.h"
19 
20 #include <QSortFilterProxyModel>
21 #include <QVariant>
22 #include <QItemSelectionModel>
23 
24 #include "qgsfeaturemodel.h"
25 #include "qgsfeature.h" // QgsFeatureId
26 #include "qgsexpressioncontext.h"
27 #include "qgsconditionalstyle.h"
28 #include "qgis_gui.h"
29 
30 class QgsAttributeTableFilterModel;
31 class QgsAttributeTableModel;
32 class QgsVectorLayerCache;
33 
34 /**
35  * \ingroup gui
36  * \class QgsFeatureListModel
37  */
38 class GUI_EXPORT QgsFeatureListModel : public QSortFilterProxyModel, public QgsFeatureModel
39 {
40     Q_OBJECT
41 
42   public:
43     struct FeatureInfo
44     {
45       public:
46 
47         /**
48          * Constructor for FeatureInfo.
49          */
50         FeatureInfo() = default;
51 
52         //! True if feature is a newly added feature.
53         bool isNew = false;
54 
55         //! True if feature has been edited.
56         bool isEdited = false;
57     };
58 
59     enum Role
60     {
61       FeatureInfoRole = 0x1000, // Make sure no collisions with roles on QgsAttributeTableModel
62       FeatureRole
63     };
64 
65   public:
66 
67     //! Constructor for QgsFeatureListModel
68     explicit QgsFeatureListModel( QgsAttributeTableFilterModel *sourceModel, QObject *parent SIP_TRANSFERTHIS = nullptr );
69 
70     virtual void setSourceModel( QgsAttributeTableFilterModel *sourceModel );
71 
72     /**
73      * Returns the vector layer cache which is being used to populate the model.
74      */
75     QgsVectorLayerCache *layerCache();
76 
77     QVariant data( const QModelIndex &index, int role ) const override;
78     Qt::ItemFlags flags( const QModelIndex &index ) const override;
79 
80     /**
81      * \brief If TRUE is specified, a NULL value will be injected
82      * \param injectNull state of null value injection
83      * \note If set to TRUE, the sort by display expression cannot be used
84      * \since QGIS 2.9
85      */
86     void setInjectNull( bool injectNull );
87 
88     /**
89      * \brief Returns the current state of null value injection
90      * \returns If a NULL value is added
91      * \since QGIS 2.9
92      */
93     bool injectNull();
94 
95     QgsAttributeTableModel *masterModel();
96 
97     /**
98      *  \param  expression   A QgsExpression compatible string.
99      *  \returns TRUE if the expression could be set, FALSE if there was a parse error.
100      *          If it fails, the old expression will still be applied. Call parserErrorString()
101      *          for a meaningful error message.
102      */
103     bool setDisplayExpression( const QString &expression );
104 
105     /**
106      * \brief Returns a detailed message about errors while parsing a QgsExpression.
107      * \returns A message containing information about the parser error.
108      */
109     QString parserErrorString();
110 
111     QString displayExpression() const;
112     bool featureByIndex( const QModelIndex &index, QgsFeature &feat );
113 
114     /**
115      * Returns the feature ID corresponding to an \a index from the model.
116      * \see fidToIdx()
117      */
118     QgsFeatureId idxToFid( const QModelIndex &index ) const;
119 
120     /**
121      * Returns the model index corresponding to a feature ID.
122      * \see idxToFid()
123      */
124     QModelIndex fidToIdx( QgsFeatureId fid ) const;
125 
126     QModelIndex mapToSource( const QModelIndex &proxyIndex ) const override;
127     QModelIndex mapFromSource( const QModelIndex &sourceIndex ) const override;
128 
129     virtual QModelIndex mapToMaster( const QModelIndex &proxyIndex ) const;
130     virtual QModelIndex mapFromMaster( const QModelIndex &sourceIndex ) const;
131 
132     virtual QItemSelection mapSelectionFromMaster( const QItemSelection &selection ) const;
133     virtual QItemSelection mapSelectionToMaster( const QItemSelection &selection ) const;
134 
135     QModelIndex parent( const QModelIndex &child ) const override;
136     int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
137     int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
138 
139     QModelIndex fidToIndex( QgsFeatureId fid ) override;
140     QModelIndexList fidToIndexList( QgsFeatureId fid );
141 
142     /**
143      * Sort this model by its display expression.
144      *
145      * \since QGIS 3.2
146      */
147     bool sortByDisplayExpression() const;
148 
149     /**
150      * Sort this model by its display expression.
151      *
152      * \note Not compatible with injectNull, if sorting by display expression is enabled,
153      * injectNull will automatically turned off.
154      *
155      * \since QGIS 3.2
156      */
157     void setSortByDisplayExpression( bool sortByDisplayExpression, Qt::SortOrder order = Qt::AscendingOrder );
158 
159   public slots:
160 
161     /**
162      * Does nothing except for calling beginRemoveRows()
163      *
164      * \deprecated Use beginRemoveRows() instead
165      */
166     Q_DECL_DEPRECATED void onBeginRemoveRows( const QModelIndex &parent, int first, int last );
167 
168     /**
169      * Does nothing except for calling endRemoveRows()
170      *
171      * \deprecated Use endRemoveRows() instead
172      */
173     Q_DECL_DEPRECATED void onEndRemoveRows( const QModelIndex &parent, int first, int last );
174 
175     /**
176      * Does nothing except for calling beginInsertRows()
177      *
178      * \deprecated use beginInsertRows() instead
179      */
180     Q_DECL_DEPRECATED void onBeginInsertRows( const QModelIndex &parent, int first, int last );
181 
182     /**
183      * Does nothing except for calling endInsertRows()
184      *
185      * \deprecated use endInsertRows() instead
186      */
187     Q_DECL_DEPRECATED void onEndInsertRows( const QModelIndex &parent, int first, int last );
188 
189   private slots:
190 
191     void conditionalStylesChanged();
192 
193   private:
194     mutable QgsExpression mDisplayExpression;
195     QgsAttributeTableFilterModel *mFilterModel = nullptr;
196     QString mParserErrorString;
197     bool mInjectNull = false;
198     mutable QgsExpressionContext mExpressionContext;
199     mutable QMap< QgsFeatureId, QList<QgsConditionalStyle> > mRowStylesMap;
200     bool mSortByDisplayExpression = false;
201     QPointer< QgsVectorLayer > mSourceLayer;
202 };
203 
204 Q_DECLARE_METATYPE( QgsFeatureListModel::FeatureInfo )
205 
206 #endif // QGSATTRIBUTEEDITORMODEL_H
207