@@ -48,6 +48,7 @@ QgsDualView::QgsDualView( QWidget* parent )
48
48
, mProgressDlg( nullptr )
49
49
, mFeatureSelectionManager( nullptr )
50
50
, mAttributeEditorScrollArea( nullptr )
51
+ , mMapCanvas( nullptr )
51
52
{
52
53
setupUi ( this );
53
54
@@ -67,27 +68,31 @@ QgsDualView::QgsDualView( QWidget* parent )
67
68
connect ( mFeatureList , SIGNAL ( displayExpressionChanged ( QString ) ), this , SLOT ( previewExpressionChanged ( QString ) ) );
68
69
}
69
70
70
- void QgsDualView::init ( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context )
71
+ void QgsDualView::init ( QgsVectorLayer * layer, QgsMapCanvas * mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context, bool loadFeatures )
71
72
{
73
+ mMapCanvas = mapCanvas;
74
+
72
75
if ( !layer )
73
76
return ;
74
77
78
+ mLayer = layer;
79
+
75
80
mEditorContext = context;
76
81
77
82
connect ( mTableView , SIGNAL ( willShowContextMenu ( QMenu*, QModelIndex ) ), this , SLOT ( viewWillShowContextMenu ( QMenu*, QModelIndex ) ) );
78
83
mTableView ->horizontalHeader ()->setContextMenuPolicy ( Qt::CustomContextMenu );
79
84
connect ( mTableView ->horizontalHeader (), SIGNAL ( customContextMenuRequested ( QPoint ) ), this , SLOT ( showViewHeaderMenu ( QPoint ) ) );
80
85
connect ( mTableView , SIGNAL ( columnResized ( int , int ) ), this , SLOT ( tableColumnResized ( int , int ) ) );
81
86
82
- initLayerCache ( layer, !request.filterRect ().isNull () );
83
- initModels ( mapCanvas, request );
87
+ initLayerCache ( !( request. flags () & QgsFeatureRequest::NoGeometry ) || !request.filterRect ().isNull () );
88
+ initModels ( mapCanvas, request, loadFeatures );
84
89
85
- mConditionalFormatWidget ->setLayer ( layer );
90
+ mConditionalFormatWidget ->setLayer ( mLayer );
86
91
87
92
mTableView ->setModel ( mFilterModel );
88
93
mFeatureList ->setModel ( mFeatureListModel );
89
94
delete mAttributeForm ;
90
- mAttributeForm = new QgsAttributeForm ( layer , QgsFeature (), mEditorContext );
95
+ mAttributeForm = new QgsAttributeForm ( mLayer , QgsFeature (), mEditorContext );
91
96
if ( !context.parentContext () )
92
97
{
93
98
mAttributeEditorScrollArea = new QScrollArea ();
@@ -119,27 +124,27 @@ void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const Qg
119
124
void QgsDualView::columnBoxInit ()
120
125
{
121
126
// load fields
122
- QList<QgsField> fields = mLayerCache -> layer () ->fields ().toList ();
127
+ QList<QgsField> fields = mLayer ->fields ().toList ();
123
128
124
129
QString defaultField;
125
130
126
131
// default expression: saved value
127
- QString displayExpression = mLayerCache -> layer () ->displayExpression ();
132
+ QString displayExpression = mLayer ->displayExpression ();
128
133
129
134
// if no display expression is saved: use display field instead
130
135
if ( displayExpression.isEmpty () )
131
136
{
132
- if ( !mLayerCache -> layer () ->displayField ().isEmpty () )
137
+ if ( !mLayer ->displayField ().isEmpty () )
133
138
{
134
- defaultField = mLayerCache -> layer () ->displayField ();
139
+ defaultField = mLayer ->displayField ();
135
140
displayExpression = QString ( " COALESCE(\" %1\" , '<NULL>')" ).arg ( defaultField );
136
141
}
137
142
}
138
143
139
144
// if neither display expression nor display field is saved...
140
145
if ( displayExpression.isEmpty () )
141
146
{
142
- QgsAttributeList pkAttrs = mLayerCache -> layer () ->pkAttributeList ();
147
+ QgsAttributeList pkAttrs = mLayer ->pkAttributeList ();
143
148
144
149
if ( !pkAttrs.isEmpty () )
145
150
{
@@ -182,13 +187,13 @@ void QgsDualView::columnBoxInit()
182
187
183
188
Q_FOREACH ( const QgsField& field, fields )
184
189
{
185
- int fieldIndex = mLayerCache -> layer () ->fieldNameIndex ( field.name () );
190
+ int fieldIndex = mLayer ->fieldNameIndex ( field.name () );
186
191
if ( fieldIndex == -1 )
187
192
continue ;
188
193
189
- if ( mLayerCache -> layer () ->editFormConfig ()->widgetType ( fieldIndex ) != " Hidden" )
194
+ if ( mLayer ->editFormConfig ()->widgetType ( fieldIndex ) != " Hidden" )
190
195
{
191
- QIcon icon = mLayerCache -> layer () ->fields ().iconForField ( fieldIndex );
196
+ QIcon icon = mLayer ->fields ().iconForField ( fieldIndex );
192
197
QString text = field.name ();
193
198
194
199
// Generate action for the preview popup button of the feature list
@@ -233,6 +238,71 @@ QgsDualView::ViewMode QgsDualView::view() const
233
238
234
239
void QgsDualView::setFilterMode ( QgsAttributeTableFilterModel::FilterMode filterMode )
235
240
{
241
+ // cleanup any existing connections
242
+ switch ( mFilterModel ->filterMode () )
243
+ {
244
+ case QgsAttributeTableFilterModel::ShowVisible:
245
+ disconnect ( mMapCanvas , SIGNAL ( extentsChanged () ), this , SLOT ( extentChanged () ) );
246
+ break ;
247
+
248
+ case QgsAttributeTableFilterModel::ShowAll:
249
+ case QgsAttributeTableFilterModel::ShowEdited:
250
+ case QgsAttributeTableFilterModel::ShowFilteredList:
251
+ break ;
252
+
253
+ case QgsAttributeTableFilterModel::ShowSelected:
254
+ disconnect ( masterModel ()->layer (), SIGNAL ( selectionChanged () ), this ,
255
+ SLOT ( updateSelectedFeatures () ) );
256
+ break ;
257
+ }
258
+
259
+ QgsFeatureRequest r = mMasterModel ->request ();
260
+ bool needsGeometry = filterMode == QgsAttributeTableFilterModel::ShowVisible;
261
+
262
+ bool requiresTableReload = ( r.filterType () != QgsFeatureRequest::FilterNone || !r.filterRect ().isNull () ) // previous request was subset
263
+ || ( needsGeometry && r.flags () & QgsFeatureRequest::NoGeometry ) // no geometry for last request
264
+ || ( mMasterModel ->rowCount () == 0 ); // no features
265
+
266
+ if ( !needsGeometry )
267
+ r.setFlags ( r.flags () | QgsFeatureRequest::NoGeometry );
268
+ else
269
+ r.setFlags ( r.flags () & ~( QgsFeatureRequest::NoGeometry ) );
270
+ r.setFilterFids ( QgsFeatureIds () );
271
+ r.setFilterRect ( QgsRectangle () );
272
+ r.disableFilter ();
273
+
274
+ // setup new connections and filter request parameters
275
+ switch ( filterMode )
276
+ {
277
+ case QgsAttributeTableFilterModel::ShowVisible:
278
+ connect ( mMapCanvas , SIGNAL ( extentsChanged () ), this , SLOT ( extentChanged () ) );
279
+ if ( mMapCanvas )
280
+ {
281
+ QgsRectangle rect = mMapCanvas ->mapSettings ().mapToLayerCoordinates ( mLayer , mMapCanvas ->extent () );
282
+ r.setFilterRect ( rect );
283
+ }
284
+ break ;
285
+
286
+ case QgsAttributeTableFilterModel::ShowAll:
287
+ case QgsAttributeTableFilterModel::ShowEdited:
288
+ case QgsAttributeTableFilterModel::ShowFilteredList:
289
+ break ;
290
+
291
+ case QgsAttributeTableFilterModel::ShowSelected:
292
+ connect ( masterModel ()->layer (), SIGNAL ( selectionChanged () ), this , SLOT ( updateSelectedFeatures () ) );
293
+ if ( masterModel ()->layer ()->selectedFeatureCount () > 0 )
294
+ r.setFilterFids ( masterModel ()->layer ()->selectedFeaturesIds () );
295
+ break ;
296
+ }
297
+
298
+ if ( requiresTableReload )
299
+ {
300
+ mMasterModel ->setRequest ( r );
301
+ whileBlocking ( mLayerCache )->setCacheGeometry ( needsGeometry );
302
+ mMasterModel ->loadLayer ();
303
+ }
304
+
305
+ // update filter model
236
306
mFilterModel ->setFilterMode ( filterMode );
237
307
emit filterChanged ();
238
308
}
@@ -242,23 +312,21 @@ void QgsDualView::setSelectedOnTop( bool selectedOnTop )
242
312
mFilterModel ->setSelectedOnTop ( selectedOnTop );
243
313
}
244
314
245
- void QgsDualView::initLayerCache ( QgsVectorLayer* layer, bool cacheGeometry )
315
+ void QgsDualView::initLayerCache ( bool cacheGeometry )
246
316
{
247
317
// Initialize the cache
248
318
QSettings settings;
249
319
int cacheSize = settings.value ( " /qgis/attributeTableRowCache" , " 10000" ).toInt ();
250
- mLayerCache = new QgsVectorLayerCache ( layer , cacheSize, this );
320
+ mLayerCache = new QgsVectorLayerCache ( mLayer , cacheSize, this );
251
321
mLayerCache ->setCacheGeometry ( cacheGeometry );
252
- if ( 0 == cacheSize || 0 == ( QgsVectorDataProvider::SelectAtId & mLayerCache -> layer () ->dataProvider ()->capabilities () ) )
322
+ if ( 0 == cacheSize || 0 == ( QgsVectorDataProvider::SelectAtId & mLayer ->dataProvider ()->capabilities () ) )
253
323
{
254
- connect ( mLayerCache , SIGNAL ( progress ( int , bool & ) ), this , SLOT ( progress ( int , bool & ) ) );
255
- connect ( mLayerCache , SIGNAL ( finished () ), this , SLOT ( finished () ) );
256
-
257
- mLayerCache ->setFullCache ( true );
324
+ connect ( mLayerCache , SIGNAL ( invalidated () ), this , SLOT ( rebuildFullLayerCache () ) );
325
+ rebuildFullLayerCache ();
258
326
}
259
327
}
260
328
261
- void QgsDualView::initModels ( QgsMapCanvas* mapCanvas, const QgsFeatureRequest& request )
329
+ void QgsDualView::initModels ( QgsMapCanvas * mapCanvas, const QgsFeatureRequest & request, bool loadFeatures )
262
330
{
263
331
delete mFeatureListModel ;
264
332
delete mFilterModel ;
@@ -274,7 +342,8 @@ void QgsDualView::initModels( QgsMapCanvas* mapCanvas, const QgsFeatureRequest&
274
342
275
343
connect ( mConditionalFormatWidget , SIGNAL ( rulesUpdated ( QString ) ), mMasterModel , SLOT ( fieldConditionalStyleChanged ( QString ) ) );
276
344
277
- mMasterModel ->loadLayer ();
345
+ if ( loadFeatures )
346
+ mMasterModel ->loadLayer ();
278
347
279
348
mFilterModel = new QgsAttributeTableFilterModel ( mapCanvas, mMasterModel , mMasterModel );
280
349
@@ -285,13 +354,13 @@ void QgsDualView::initModels( QgsMapCanvas* mapCanvas, const QgsFeatureRequest&
285
354
286
355
void QgsDualView::on_mFeatureList_aboutToChangeEditSelection ( bool & ok )
287
356
{
288
- if ( mLayerCache -> layer () ->isEditable () && !mAttributeForm ->save () )
357
+ if ( mLayer ->isEditable () && !mAttributeForm ->save () )
289
358
ok = false ;
290
359
}
291
360
292
361
void QgsDualView::on_mFeatureList_currentEditSelectionChanged ( const QgsFeature &feat )
293
362
{
294
- if ( !mLayerCache -> layer () ->isEditable () || mAttributeForm ->save () )
363
+ if ( !mLayer ->isEditable () || mAttributeForm ->save () )
295
364
{
296
365
mAttributeForm ->setFeature ( feat );
297
366
setCurrentEditSelection ( QgsFeatureIds () << feat.id () );
@@ -346,9 +415,9 @@ void QgsDualView::previewExpressionBuilder()
346
415
QgsExpressionContext context;
347
416
context << QgsExpressionContextUtils::globalScope ()
348
417
<< QgsExpressionContextUtils::projectScope ()
349
- << QgsExpressionContextUtils::layerScope ( mLayerCache -> layer () );
418
+ << QgsExpressionContextUtils::layerScope ( mLayer );
350
419
351
- QgsExpressionBuilderDialog dlg ( mLayerCache -> layer () , mFeatureList ->displayExpression (), this , " generic" , context );
420
+ QgsExpressionBuilderDialog dlg ( mLayer , mFeatureList ->displayExpression (), this , " generic" , context );
352
421
dlg.setWindowTitle ( tr ( " Expression based preview" ) );
353
422
dlg.setExpressionText ( mFeatureList ->displayExpression () );
354
423
@@ -433,15 +502,15 @@ void QgsDualView::viewWillShowContextMenu( QMenu* menu, const QModelIndex& atInd
433
502
}
434
503
435
504
// add user-defined actions to context menu
436
- if ( mLayerCache -> layer () ->actions ()->size () != 0 )
505
+ if ( mLayer ->actions ()->size () != 0 )
437
506
{
438
507
439
508
QAction *a = menu->addAction ( tr ( " Run layer action" ) );
440
509
a->setEnabled ( false );
441
510
442
- for ( int i = 0 ; i < mLayerCache -> layer () ->actions ()->size (); i++ )
511
+ for ( int i = 0 ; i < mLayer ->actions ()->size (); i++ )
443
512
{
444
- const QgsAction &action = mLayerCache -> layer () ->actions ()->at ( i );
513
+ const QgsAction &action = mLayer ->actions ()->at ( i );
445
514
446
515
if ( !action.runable () )
447
516
continue ;
@@ -452,7 +521,7 @@ void QgsDualView::viewWillShowContextMenu( QMenu* menu, const QModelIndex& atInd
452
521
}
453
522
454
523
// add actions from QgsMapLayerActionRegistry to context menu
455
- QList<QgsMapLayerAction *> registeredActions = QgsMapLayerActionRegistry::instance ()->mapLayerActions ( mLayerCache -> layer () );
524
+ QList<QgsMapLayerAction *> registeredActions = QgsMapLayerActionRegistry::instance ()->mapLayerActions ( mLayer );
456
525
if ( !registeredActions.isEmpty () )
457
526
{
458
527
// add a separator between user defined and standard actions
@@ -504,12 +573,12 @@ void QgsDualView::showViewHeaderMenu( QPoint point )
504
573
505
574
void QgsDualView::organizeColumns ()
506
575
{
507
- if ( !mLayerCache -> layer () )
576
+ if ( !mLayer )
508
577
{
509
578
return ;
510
579
}
511
580
512
- QgsOrganizeTableColumnsDialog dialog ( mLayerCache -> layer () , this );
581
+ QgsOrganizeTableColumnsDialog dialog ( mLayer , this );
513
582
if ( dialog.exec () == QDialog::Accepted )
514
583
{
515
584
QgsAttributeTableConfig config = dialog.config ();
@@ -573,8 +642,7 @@ void QgsDualView::autosizeColumn()
573
642
574
643
void QgsDualView::modifySort ()
575
644
{
576
- QgsVectorLayer* layer = mLayerCache ->layer ();
577
- if ( !layer )
645
+ if ( !mLayer )
578
646
return ;
579
647
580
648
QgsAttributeTableConfig config = mConfig ;
@@ -598,12 +666,12 @@ void QgsDualView::modifySort()
598
666
QgsExpressionContext context;
599
667
context << QgsExpressionContextUtils::globalScope ()
600
668
<< QgsExpressionContextUtils::projectScope ()
601
- << QgsExpressionContextUtils::layerScope ( layer );
669
+ << QgsExpressionContextUtils::layerScope ( mLayer );
602
670
expressionBuilder->setExpressionContext ( context );
603
- expressionBuilder->setLayer ( layer );
671
+ expressionBuilder->setLayer ( mLayer );
604
672
expressionBuilder->loadFieldNames ();
605
673
expressionBuilder->loadRecent ( " generic" );
606
- expressionBuilder->setExpressionText ( sortExpression ().isEmpty () ? layer ->displayExpression () : sortExpression () );
674
+ expressionBuilder->setExpressionText ( sortExpression ().isEmpty () ? mLayer ->displayExpression () : sortExpression () );
607
675
608
676
sortingGroupBox->layout ()->addWidget ( expressionBuilder );
609
677
@@ -644,18 +712,26 @@ void QgsDualView::zoomToCurrentFeature()
644
712
QgsMapCanvas* canvas = mFilterModel ->mapCanvas ();
645
713
if ( canvas )
646
714
{
647
- canvas->zoomToFeatureIds ( mLayerCache -> layer () , ids );
715
+ canvas->zoomToFeatureIds ( mLayer , ids );
648
716
}
649
717
}
650
718
719
+ void QgsDualView::rebuildFullLayerCache ()
720
+ {
721
+ connect ( mLayerCache , SIGNAL ( progress ( int , bool & ) ), this , SLOT ( progress ( int , bool & ) ), Qt::UniqueConnection );
722
+ connect ( mLayerCache , SIGNAL ( finished () ), this , SLOT ( finished () ), Qt::UniqueConnection );
723
+
724
+ mLayerCache ->setFullCache ( true );
725
+ }
726
+
651
727
void QgsDualView::previewExpressionChanged ( const QString& expression )
652
728
{
653
- mLayerCache -> layer () ->setDisplayExpression ( expression );
729
+ mLayer ->setDisplayExpression ( expression );
654
730
}
655
731
656
732
void QgsDualView::onSortColumnChanged ()
657
733
{
658
- QgsAttributeTableConfig cfg = mLayerCache -> layer () ->attributeTableConfig ();
734
+ QgsAttributeTableConfig cfg = mLayer ->attributeTableConfig ();
659
735
cfg.setSortExpression ( mFilterModel ->sortExpression () );
660
736
cfg.setSortOrder ( mFilterModel ->sortOrder () );
661
737
setAttributeTableConfig ( cfg );
@@ -671,6 +747,34 @@ void QgsDualView::sortByPreviewExpression()
671
747
setSortExpression ( mFeatureList ->displayExpression (), sortOrder );
672
748
}
673
749
750
+ void QgsDualView::updateSelectedFeatures ()
751
+ {
752
+ QgsFeatureRequest r = mMasterModel ->request ();
753
+ if ( r.filterType () == QgsFeatureRequest::FilterNone && r.filterRect ().isNull () )
754
+ return ; // already requested all features
755
+
756
+ if ( masterModel ()->layer ()->selectedFeatureCount () > 0 )
757
+ r.setFilterFids ( masterModel ()->layer ()->selectedFeaturesIds () );
758
+ else
759
+ r.disableFilter ();
760
+ mMasterModel ->setRequest ( r );
761
+ mMasterModel ->loadLayer ();
762
+ emit filterChanged ();
763
+ }
764
+
765
+ void QgsDualView::extentChanged ()
766
+ {
767
+ QgsFeatureRequest r = mMasterModel ->request ();
768
+ if ( mMapCanvas && ( r.filterType () != QgsFeatureRequest::FilterNone || !r.filterRect ().isNull () ) )
769
+ {
770
+ QgsRectangle rect = mMapCanvas ->mapSettings ().mapToLayerCoordinates ( mLayer , mMapCanvas ->extent () );
771
+ r.setFilterRect ( rect );
772
+ mMasterModel ->setRequest ( r );
773
+ mMasterModel ->loadLayer ();
774
+ }
775
+ emit filterChanged ();
776
+ }
777
+
674
778
void QgsDualView::featureFormAttributeChanged ()
675
779
{
676
780
mFeatureList ->setCurrentFeatureEdited ( true );
@@ -699,7 +803,7 @@ void QgsDualView::setFeatureSelectionManager( QgsIFeatureSelectionManager* featu
699
803
700
804
void QgsDualView::setAttributeTableConfig ( const QgsAttributeTableConfig& config )
701
805
{
702
- mLayerCache -> layer () ->setAttributeTableConfig ( config );
806
+ mLayer ->setAttributeTableConfig ( config );
703
807
mFilterModel ->setAttributeTableConfig ( config );
704
808
mTableView ->setAttributeTableConfig ( config );
705
809
mConfig = config;
0 commit comments