1 /***************************************************************************
2   qgsgeopdflayertreemodel.cpp
3  ---------------------
4  begin                : August 2019
5  copyright            : (C) 2019 by Nyall Dawson
6  email                : nyall dot dawson at gmail dot 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 <QComboBox>
17 #include <QDoubleSpinBox>
18 
19 #include "qgsgeopdflayertreemodel.h"
20 #include "qgslayertree.h"
21 #include "qgsproject.h"
22 #include "qgsvectorlayer.h"
23 #include "qgsapplication.h"
24 
QgsGeoPdfLayerTreeModel(const QList<QgsMapLayer * > & layers,QObject * parent)25 QgsGeoPdfLayerTreeModel::QgsGeoPdfLayerTreeModel( const QList<QgsMapLayer *> &layers, QObject *parent )
26   : QgsMapLayerModel( layers, parent )
27 {
28   setItemsCanBeReordered( true );
29 }
30 
columnCount(const QModelIndex & parent) const31 int QgsGeoPdfLayerTreeModel::columnCount( const QModelIndex &parent ) const
32 {
33   Q_UNUSED( parent )
34   return 4;
35 }
36 
flags(const QModelIndex & idx) const37 Qt::ItemFlags QgsGeoPdfLayerTreeModel::flags( const QModelIndex &idx ) const
38 {
39   if ( !idx.isValid() )
40     return Qt::ItemIsDropEnabled;
41 
42   if ( idx.column() == IncludeVectorAttributes )
43   {
44     if ( vectorLayer( idx ) )
45       return QgsMapLayerModel::flags( idx ) | Qt::ItemIsUserCheckable;
46     else
47       return QgsMapLayerModel::flags( idx );
48   }
49 
50   if ( idx.column() == InitiallyVisible )
51   {
52     return QgsMapLayerModel::flags( idx ) | Qt::ItemIsUserCheckable;
53   }
54 
55   if ( !mapLayer( idx ) )
56     return Qt::ItemFlags();
57 
58   return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
59 }
60 
mapLayer(const QModelIndex & idx) const61 QgsMapLayer *QgsGeoPdfLayerTreeModel::mapLayer( const QModelIndex &idx ) const
62 {
63   return layerFromIndex( index( idx.row(), LayerColumn, idx.parent() ) );
64 }
65 
vectorLayer(const QModelIndex & idx) const66 QgsVectorLayer *QgsGeoPdfLayerTreeModel::vectorLayer( const QModelIndex &idx ) const
67 {
68   return qobject_cast<QgsVectorLayer *>( mapLayer( idx ) );
69 }
70 
headerData(int section,Qt::Orientation orientation,int role) const71 QVariant QgsGeoPdfLayerTreeModel::headerData( int section, Qt::Orientation orientation, int role ) const
72 {
73   if ( orientation == Qt::Horizontal )
74   {
75     if ( role == Qt::DisplayRole )
76     {
77       switch ( section )
78       {
79         case LayerColumn:
80           return tr( "Layer" );
81         case GroupColumn:
82           return tr( "PDF Group" );
83         case InitiallyVisible:
84           return tr( "Initially Visible" );
85         case IncludeVectorAttributes:
86           return tr( "Include Attributes" );
87         default:
88           return QVariant();
89       }
90     }
91   }
92   return QgsMapLayerModel::headerData( section, orientation, role );
93 }
94 
data(const QModelIndex & idx,int role) const95 QVariant QgsGeoPdfLayerTreeModel::data( const QModelIndex &idx, int role ) const
96 {
97   switch ( idx.column() )
98   {
99     case LayerColumn:
100       if ( role == Qt::CheckStateRole )
101         return QVariant();
102 
103       return QgsMapLayerModel::data( idx, role );
104 
105     case GroupColumn:
106     {
107       switch ( role )
108       {
109         case Qt::DisplayRole:
110         case Qt::EditRole:
111         {
112           if ( QgsMapLayer *ml = mapLayer( idx ) )
113           {
114             return ml->customProperty( QStringLiteral( "geopdf/groupName" ) ).toString();
115           }
116           break;
117         }
118       }
119 
120       return QVariant();
121     }
122 
123     case InitiallyVisible:
124     {
125       if ( role == Qt::CheckStateRole )
126       {
127         if ( QgsMapLayer *ml = mapLayer( idx ) )
128         {
129           const QVariant v = ml->customProperty( QStringLiteral( "geopdf/initiallyVisible" ) );
130           if ( v.isValid() )
131           {
132             return v.toBool() ? Qt::Checked : Qt::Unchecked;
133           }
134           else
135           {
136             // otherwise, we default to showing by default
137             return Qt::Checked;
138           }
139         }
140         return QVariant();
141       }
142       return QVariant();
143     }
144 
145     case IncludeVectorAttributes:
146     {
147       if ( role == Qt::CheckStateRole )
148       {
149         if ( QgsVectorLayer *vl = vectorLayer( idx ) )
150         {
151           const QVariant v = vl->customProperty( QStringLiteral( "geopdf/includeFeatures" ) );
152           if ( v.isValid() )
153           {
154             return v.toBool() ? Qt::Checked : Qt::Unchecked;
155           }
156           else
157           {
158             // otherwise, we default to true
159             return Qt::Checked;
160           }
161         }
162         return QVariant();
163       }
164     }
165   }
166 
167   return QVariant();
168 }
169 
setData(const QModelIndex & index,const QVariant & value,int role)170 bool QgsGeoPdfLayerTreeModel::setData( const QModelIndex &index, const QVariant &value, int role )
171 {
172   switch ( index.column() )
173   {
174     case IncludeVectorAttributes:
175     {
176       if ( role == Qt::CheckStateRole )
177       {
178         if ( QgsVectorLayer *vl = vectorLayer( index ) )
179         {
180           vl->setCustomProperty( QStringLiteral( "geopdf/includeFeatures" ), value.toInt() == Qt::Checked );
181           emit dataChanged( index, index );
182           return true;
183         }
184       }
185       break;
186     }
187 
188     case GroupColumn:
189     {
190       if ( role == Qt::EditRole )
191       {
192         if ( QgsMapLayer *ml = mapLayer( index ) )
193         {
194           ml->setCustomProperty( QStringLiteral( "geopdf/groupName" ), value.toString() );
195           emit dataChanged( index, index );
196           return true;
197         }
198       }
199       break;
200     }
201 
202     case InitiallyVisible:
203     {
204       if ( role == Qt::CheckStateRole )
205       {
206         if ( QgsMapLayer *ml = mapLayer( index ) )
207         {
208           ml->setCustomProperty( QStringLiteral( "geopdf/initiallyVisible" ), value.toInt() == Qt::Checked );
209           emit dataChanged( index, index );
210           return true;
211         }
212       }
213       break;
214     }
215 
216     case LayerColumn:
217       return QgsMapLayerModel::setData( index, value, role );
218   }
219   return false;
220 }
221 
checkAll(bool checked,const QModelIndex & parent,int column)222 void QgsGeoPdfLayerTreeModel::checkAll( bool checked, const QModelIndex &parent, int column )
223 {
224   for ( int row = 0; row < rowCount( parent ); ++row )
225   {
226     const QModelIndex childIndex = index( row, column, parent );
227     setData( childIndex, checked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole );
228     checkAll( checked, childIndex );
229   }
230 }
231 
232 
233 ///@cond PRIVATE
QgsGeoPdfLayerFilteredTreeModel(QgsGeoPdfLayerTreeModel * sourceModel,QObject * parent)234 QgsGeoPdfLayerFilteredTreeModel::QgsGeoPdfLayerFilteredTreeModel( QgsGeoPdfLayerTreeModel *sourceModel, QObject *parent )
235   : QSortFilterProxyModel( parent )
236   , mLayerTreeModel( sourceModel )
237 {
238   setSourceModel( sourceModel );
239 }
240 
filterAcceptsRow(int source_row,const QModelIndex & source_parent) const241 bool QgsGeoPdfLayerFilteredTreeModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const
242 {
243   if ( QgsMapLayer *layer = mLayerTreeModel->layerFromIndex( sourceModel()->index( source_row, 0, source_parent ) ) )
244   {
245     // filter out non-spatial layers
246     if ( !layer->isSpatial() )
247       return false;
248 
249   }
250   return true;
251 }
252 
253 ///@endcond
254