QGIS API Documentation  2.15.0-Master (1f0fce7)
qgsdualview.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdualview.cpp
3  --------------------------------------
4  Date : 10.2.2013
5  Copyright : (C) 2013 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 
16 #include "qgsapplication.h"
17 #include "qgsactionmanager.h"
18 #include "qgsattributetablemodel.h"
19 #include "qgsdualview.h"
21 #include "qgsfeaturelistmodel.h"
23 #include "qgsmapcanvas.h"
25 #include "qgsmessagelog.h"
26 #include "qgsvectordataprovider.h"
27 #include "qgsvectorlayercache.h"
29 
30 #include <QClipboard>
31 #include <QDialog>
32 #include <QMenu>
33 #include <QMessageBox>
34 #include <QProgressDialog>
35 #include <QSettings>
36 #include <QGroupBox>
37 #include <QInputDialog>
38 
40  : QStackedWidget( parent )
41  , mEditorContext()
42  , mMasterModel( nullptr )
43  , mFilterModel( nullptr )
44  , mFeatureListModel( nullptr )
45  , mAttributeForm( nullptr )
46  , mHorizontalHeaderMenu( nullptr )
47  , mLayerCache( nullptr )
48  , mProgressDlg( nullptr )
49  , mFeatureSelectionManager( nullptr )
50  , mAttributeEditorScrollArea( nullptr )
51 {
52  setupUi( this );
53 
54  mConditionalFormatWidget->hide();
55 
56  mPreviewActionMapper = new QSignalMapper( this );
57 
58  mPreviewColumnsMenu = new QMenu( this );
59  mActionPreviewColumnsMenu->setMenu( mPreviewColumnsMenu );
60 
61  // Set preview icon
62  mActionExpressionPreview->setIcon( QgsApplication::getThemeIcon( "/mIconExpressionPreview.svg" ) );
63 
64  // Connect layer list preview signals
65  connect( mActionExpressionPreview, SIGNAL( triggered() ), SLOT( previewExpressionBuilder() ) );
66  connect( mPreviewActionMapper, SIGNAL( mapped( QObject* ) ), SLOT( previewColumnChanged( QObject* ) ) );
67  connect( mFeatureList, SIGNAL( displayExpressionChanged( QString ) ), this, SLOT( previewExpressionChanged( QString ) ) );
68 }
69 
70 void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context )
71 {
72  if ( !layer )
73  return;
74 
75  mEditorContext = context;
76 
77  connect( mTableView, SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) );
78  mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu );
79  connect( mTableView->horizontalHeader(), SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( showViewHeaderMenu( QPoint ) ) );
80  connect( mTableView, SIGNAL( columnResized( int, int ) ), this, SLOT( tableColumnResized( int, int ) ) );
81 
82  initLayerCache( layer, !request.filterRect().isNull() );
83  initModels( mapCanvas, request );
84 
85  mConditionalFormatWidget->setLayer( layer );
86 
87  mTableView->setModel( mFilterModel );
88  mFeatureList->setModel( mFeatureListModel );
89  delete mAttributeForm;
90  mAttributeForm = new QgsAttributeForm( layer, QgsFeature(), mEditorContext );
91  if ( !context.parentContext() )
92  {
93  mAttributeEditorScrollArea = new QScrollArea();
94  mAttributeEditorScrollArea->setWidgetResizable( true );
95  mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea );
96  mAttributeEditorScrollArea->setWidget( mAttributeForm );
97  }
98  else
99  {
100  mAttributeEditor->layout()->addWidget( mAttributeForm );
101  }
102 
103  connect( mAttributeForm, SIGNAL( attributeChanged( QString, QVariant ) ), this, SLOT( featureFormAttributeChanged() ) );
104  connect( mAttributeForm, SIGNAL( modeChanged( QgsAttributeForm::Mode ) ), this, SIGNAL( formModeChanged( QgsAttributeForm::Mode ) ) );
105  connect( mMasterModel, SIGNAL( modelChanged() ), mAttributeForm, SLOT( refreshFeature() ) );
107  if ( mFeatureListPreviewButton->defaultAction() )
108  mFeatureList->setDisplayExpression( mDisplayExpression );
109  else
110  columnBoxInit();
111 
112  // This slows down load of the attribute table heaps and uses loads of memory.
113  //mTableView->resizeColumnsToContents();
114 
115  mFeatureList->setEditSelection( QgsFeatureIds() << mFeatureListModel->idxToFid( mFeatureListModel->index( 0, 0 ) ) );
116 }
117 
119 {
120  // load fields
121  QList<QgsField> fields = mLayerCache->layer()->fields().toList();
122 
123  QString defaultField;
124 
125  // default expression: saved value
126  QString displayExpression = mLayerCache->layer()->displayExpression();
127 
128  // if no display expression is saved: use display field instead
129  if ( displayExpression.isEmpty() )
130  {
131  if ( !mLayerCache->layer()->displayField().isEmpty() )
132  {
133  defaultField = mLayerCache->layer()->displayField();
134  displayExpression = QString( "COALESCE(\"%1\", '<NULL>')" ).arg( defaultField );
135  }
136  }
137 
138  // if neither display expression nor display field is saved...
139  if ( displayExpression.isEmpty() )
140  {
141  QgsAttributeList pkAttrs = mLayerCache->layer()->pkAttributeList();
142 
143  if ( !pkAttrs.isEmpty() )
144  {
145  if ( pkAttrs.size() == 1 )
146  defaultField = pkAttrs.at( 0 );
147 
148  // ... If there are primary key(s) defined
149  QStringList pkFields;
150 
151  Q_FOREACH ( int attr, pkAttrs )
152  {
153  pkFields.append( "COALESCE(\"" + fields[attr].name() + "\", '<NULL>')" );
154  }
155 
156  displayExpression = pkFields.join( "||', '||" );
157  }
158  else if ( !fields.isEmpty() )
159  {
160  if ( fields.size() == 1 )
161  defaultField = fields.at( 0 ).name();
162 
163  // ... concat all fields
164  QStringList fieldNames;
165  Q_FOREACH ( const QgsField& field, fields )
166  {
167  fieldNames.append( "COALESCE(\"" + field.name() + "\", '<NULL>')" );
168  }
169 
170  displayExpression = fieldNames.join( "||', '||" );
171  }
172  else
173  {
174  // ... there isn't really much to display
175  displayExpression = "'[Please define preview text]'";
176  }
177  }
178 
179  mFeatureListPreviewButton->addAction( mActionExpressionPreview );
180  mFeatureListPreviewButton->addAction( mActionPreviewColumnsMenu );
181 
182  Q_FOREACH ( const QgsField& field, fields )
183  {
184  int fieldIndex = mLayerCache->layer()->fieldNameIndex( field.name() );
185  if ( fieldIndex == -1 )
186  continue;
187 
188  if ( mLayerCache->layer()->editFormConfig()->widgetType( fieldIndex ) != "Hidden" )
189  {
190  QIcon icon = mLayerCache->layer()->fields().iconForField( fieldIndex );
191  QString text = field.name();
192 
193  // Generate action for the preview popup button of the feature list
194  QAction* previewAction = new QAction( icon, text, mFeatureListPreviewButton );
195  mPreviewActionMapper->setMapping( previewAction, previewAction );
196  connect( previewAction, SIGNAL( triggered() ), mPreviewActionMapper, SLOT( map() ) );
197  mPreviewColumnsMenu->addAction( previewAction );
198 
199  if ( text == defaultField )
200  {
201  mFeatureListPreviewButton->setDefaultAction( previewAction );
202  }
203  }
204  }
205 
206  // If there is no single field found as preview
207  if ( !mFeatureListPreviewButton->defaultAction() )
208  {
209  mFeatureList->setDisplayExpression( displayExpression );
210  mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
211  mDisplayExpression = mFeatureList->displayExpression();
212  }
213  else
214  {
215  mFeatureListPreviewButton->defaultAction()->trigger();
216  }
217 
218  QAction* sortByPreviewExpression = new QAction( QgsApplication::getThemeIcon( "sort.svg" ), tr( "Sort by preview expression" ), this );
219  connect( sortByPreviewExpression, SIGNAL( triggered( bool ) ), this, SLOT( sortByPreviewExpression() ) );
220  mFeatureListPreviewButton->addAction( sortByPreviewExpression );
221 }
222 
224 {
225  setCurrentIndex( view );
226 }
227 
229 {
230  return static_cast< QgsDualView::ViewMode >( currentIndex() );
231 }
232 
234 {
235  mFilterModel->setFilterMode( filterMode );
236  emit filterChanged();
237 }
238 
239 void QgsDualView::setSelectedOnTop( bool selectedOnTop )
240 {
241  mFilterModel->setSelectedOnTop( selectedOnTop );
242 }
243 
244 void QgsDualView::initLayerCache( QgsVectorLayer* layer, bool cacheGeometry )
245 {
246  // Initialize the cache
247  QSettings settings;
248  int cacheSize = settings.value( "/qgis/attributeTableRowCache", "10000" ).toInt();
249  mLayerCache = new QgsVectorLayerCache( layer, cacheSize, this );
250  mLayerCache->setCacheGeometry( cacheGeometry );
251  if ( 0 == cacheSize || 0 == ( QgsVectorDataProvider::SelectAtId & mLayerCache->layer()->dataProvider()->capabilities() ) )
252  {
253  connect( mLayerCache, SIGNAL( progress( int, bool & ) ), this, SLOT( progress( int, bool & ) ) );
254  connect( mLayerCache, SIGNAL( finished() ), this, SLOT( finished() ) );
255 
256  mLayerCache->setFullCache( true );
257  }
258 }
259 
260 void QgsDualView::initModels( QgsMapCanvas* mapCanvas, const QgsFeatureRequest& request )
261 {
262  delete mFeatureListModel;
263  delete mFilterModel;
264  delete mMasterModel;
265 
266  mMasterModel = new QgsAttributeTableModel( mLayerCache, this );
267  mMasterModel->setRequest( request );
268  mMasterModel->setEditorContext( mEditorContext );
269  mMasterModel->setExtraColumns( 1 ); // Add one extra column which we can "abuse" as an action column
270 
271  connect( mMasterModel, SIGNAL( progress( int, bool & ) ), this, SLOT( progress( int, bool & ) ) );
272  connect( mMasterModel, SIGNAL( finished() ), this, SLOT( finished() ) );
273 
274  connect( mConditionalFormatWidget, SIGNAL( rulesUpdated( QString ) ), mMasterModel, SLOT( fieldConditionalStyleChanged( QString ) ) );
275 
276  mMasterModel->loadLayer();
277 
278  mFilterModel = new QgsAttributeTableFilterModel( mapCanvas, mMasterModel, mMasterModel );
279 
280  connect( mFeatureList, SIGNAL( displayExpressionChanged( QString ) ), this, SIGNAL( displayExpressionChanged( QString ) ) );
281 
282  mFeatureListModel = new QgsFeatureListModel( mFilterModel, mFilterModel );
283 }
284 
285 void QgsDualView::on_mFeatureList_aboutToChangeEditSelection( bool& ok )
286 {
287  if ( mLayerCache->layer()->isEditable() && !mAttributeForm->save() )
288  ok = false;
289 }
290 
291 void QgsDualView::on_mFeatureList_currentEditSelectionChanged( const QgsFeature &feat )
292 {
293  if ( !mLayerCache->layer()->isEditable() || mAttributeForm->save() )
294  {
295  mAttributeForm->setFeature( feat );
297  }
298  else
299  {
300  // Couldn't save feature
301  }
302 }
303 
305 {
306  mFeatureList->setCurrentFeatureEdited( false );
307  mFeatureList->setEditSelection( fids );
308 }
309 
311 {
312  return mAttributeForm->save();
313 }
314 
316 {
317  mConditionalFormatWidget->setVisible( !mConditionalFormatWidget->isVisible() );
318  mConditionalFormatWidget->viewRules();
319 }
320 
322 {
323  if ( enabled )
325 
327 }
328 
330 {
331  if ( enabled )
332  {
334  mAttributeForm->setMode( QgsAttributeForm::SearchMode );
335  }
336  else
337  {
338  mAttributeForm->setMode( QgsAttributeForm::SingleEditMode );
339  }
340 }
341 
342 void QgsDualView::previewExpressionBuilder()
343 {
344  // Show expression builder
345  QgsExpressionContext context;
348  << QgsExpressionContextUtils::layerScope( mLayerCache->layer() );
349 
350  QgsExpressionBuilderDialog dlg( mLayerCache->layer(), mFeatureList->displayExpression(), this, "generic", context );
351  dlg.setWindowTitle( tr( "Expression based preview" ) );
352  dlg.setExpressionText( mFeatureList->displayExpression() );
353 
354  if ( dlg.exec() == QDialog::Accepted )
355  {
356  mFeatureList->setDisplayExpression( dlg.expressionText() );
357  mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
358  mFeatureListPreviewButton->setPopupMode( QToolButton::MenuButtonPopup );
359  }
360 
361  mDisplayExpression = mFeatureList->displayExpression();
362 }
363 
364 void QgsDualView::previewColumnChanged( QObject* action )
365 {
366  QAction* previewAction = qobject_cast< QAction* >( action );
367 
368  if ( previewAction )
369  {
370  if ( !mFeatureList->setDisplayExpression( QString( "COALESCE( \"%1\", '<NULL>' )" ).arg( previewAction->text() ) ) )
371  {
372  QMessageBox::warning( this,
373  tr( "Could not set preview column" ),
374  tr( "Could not set column '%1' as preview column.\nParser error:\n%2" )
375  .arg( previewAction->text(), mFeatureList->parserErrorString() )
376  );
377  }
378  else
379  {
380  mFeatureListPreviewButton->setDefaultAction( previewAction );
381  mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
382  }
383  }
384 
385  mDisplayExpression = mFeatureList->displayExpression();
386 
387  Q_ASSERT( previewAction );
388 }
389 
391 {
392  return mMasterModel->rowCount();
393 }
394 
396 {
397  return mFilterModel->rowCount();
398 }
399 
401 {
402  QAction* action = qobject_cast<QAction*>( sender() );
403 
404  if ( action && action->data().isValid() && action->data().canConvert<QModelIndex>() )
405  {
406  QModelIndex index = action->data().value<QModelIndex>();
407  QVariant var = masterModel()->data( index, Qt::DisplayRole );
408  QApplication::clipboard()->setText( var.toString() );
409  }
410 }
411 
412 void QgsDualView::viewWillShowContextMenu( QMenu* menu, const QModelIndex& atIndex )
413 {
414  if ( !menu )
415  {
416  return;
417  }
418 
419 
420  QModelIndex sourceIndex = mFilterModel->mapToSource( atIndex );
421 
422  QAction *copyContentAction = new QAction( tr( "Copy cell content" ), this );
423  copyContentAction->setData( QVariant::fromValue<QModelIndex>( sourceIndex ) );
424  menu->addAction( copyContentAction );
425  connect( copyContentAction, SIGNAL( triggered() ), this, SLOT( copyCellContent() ) );
426 
427  QgsVectorLayer* vl = mFilterModel->layer();
428  QgsMapCanvas* canvas = mFilterModel->mapCanvas();
429  if ( canvas && vl && vl->geometryType() != QGis::NoGeometry )
430  {
431  menu->addAction( tr( "Zoom to feature" ), this, SLOT( zoomToCurrentFeature() ) );
432  }
433 
434  //add user-defined actions to context menu
435  if ( mLayerCache->layer()->actions()->size() != 0 )
436  {
437 
438  QAction *a = menu->addAction( tr( "Run layer action" ) );
439  a->setEnabled( false );
440 
441  for ( int i = 0; i < mLayerCache->layer()->actions()->size(); i++ )
442  {
443  const QgsAction &action = mLayerCache->layer()->actions()->at( i );
444 
445  if ( !action.runable() )
446  continue;
447 
448  QgsAttributeTableAction *a = new QgsAttributeTableAction( action.name(), this, i, sourceIndex );
449  menu->addAction( action.name(), a, SLOT( execute() ) );
450  }
451  }
452 
453  //add actions from QgsMapLayerActionRegistry to context menu
455  if ( !registeredActions.isEmpty() )
456  {
457  //add a separator between user defined and standard actions
458  menu->addSeparator();
459 
461  for ( actionIt = registeredActions.begin(); actionIt != registeredActions.end(); ++actionIt )
462  {
463  QgsAttributeTableMapLayerAction *a = new QgsAttributeTableMapLayerAction(( *actionIt )->text(), this, ( *actionIt ), sourceIndex );
464  menu->addAction(( *actionIt )->text(), a, SLOT( execute() ) );
465  }
466  }
467 
468  menu->addSeparator();
469  QgsAttributeTableAction *a = new QgsAttributeTableAction( tr( "Open form" ), this, -1, sourceIndex );
470  menu->addAction( tr( "Open form" ), a, SLOT( featureForm() ) );
471 }
472 
473 void QgsDualView::showViewHeaderMenu( QPoint point )
474 {
475  int col = mTableView->columnAt( point.x() );
476 
477  delete mHorizontalHeaderMenu;
478  mHorizontalHeaderMenu = new QMenu( this );
479 
480  QAction* hide = new QAction( tr( "&Hide column" ), mHorizontalHeaderMenu );
481  connect( hide, SIGNAL( triggered( bool ) ), this, SLOT( hideColumn() ) );
482  hide->setData( col );
483  mHorizontalHeaderMenu->addAction( hide );
484  QAction* setWidth = new QAction( tr( "&Set width..." ), mHorizontalHeaderMenu );
485  connect( setWidth, SIGNAL( triggered( bool ) ), this, SLOT( resizeColumn() ) );
486  setWidth->setData( col );
487  mHorizontalHeaderMenu->addAction( setWidth );
488  QAction* optimizeWidth = new QAction( tr( "&Autosize" ), mHorizontalHeaderMenu );
489  connect( optimizeWidth, SIGNAL( triggered( bool ) ), this, SLOT( autosizeColumn() ) );
490  optimizeWidth->setData( col );
491  mHorizontalHeaderMenu->addAction( optimizeWidth );
492 
493  mHorizontalHeaderMenu->addSeparator();
494  QAction* organize = new QAction( tr( "&Organize columns..." ), mHorizontalHeaderMenu );
495  connect( organize, SIGNAL( triggered( bool ) ), this, SLOT( organizeColumns() ) );
496  mHorizontalHeaderMenu->addAction( organize );
497  QAction* sort = new QAction( tr( "&Sort..." ), mHorizontalHeaderMenu );
498  connect( sort, SIGNAL( triggered( bool ) ), this, SLOT( modifySort() ) );
499  mHorizontalHeaderMenu->addAction( sort );
500 
501  mHorizontalHeaderMenu->popup( mTableView->horizontalHeader()->mapToGlobal( point ) );
502 }
503 
504 void QgsDualView::organizeColumns()
505 {
506  if ( !mLayerCache->layer() )
507  {
508  return;
509  }
510 
511  QgsOrganizeTableColumnsDialog dialog( mLayerCache->layer(), this );
512  if ( dialog.exec() == QDialog::Accepted )
513  {
514  QgsAttributeTableConfig config = dialog.config();
515  mLayerCache->layer()->setAttributeTableConfig( config );
516  setAttributeTableConfig( config );
517  }
518 }
519 
520 void QgsDualView::tableColumnResized( int column, int width )
521 {
522  QgsAttributeTableConfig config = mConfig;
523  int sourceCol = config.mapVisibleColumnToIndex( column );
524  if ( sourceCol >= 0 )
525  {
526  config.setColumnWidth( sourceCol, width );
527  mLayerCache->layer()->setAttributeTableConfig( config );
528  mConfig = config;
529  }
530 }
531 
532 void QgsDualView::hideColumn()
533 {
534  QAction* action = qobject_cast<QAction*>( sender() );
535  int col = action->data().toInt();
536  QgsAttributeTableConfig config = mConfig;
537  int sourceCol = mConfig.mapVisibleColumnToIndex( col );
538  if ( sourceCol >= 0 )
539  {
540  config.setColumnHidden( sourceCol, true );
541  mLayerCache->layer()->setAttributeTableConfig( config );
542  setAttributeTableConfig( config );
543  }
544 }
545 
546 void QgsDualView::resizeColumn()
547 {
548  QAction* action = qobject_cast<QAction*>( sender() );
549  int col = action->data().toInt();
550  if ( col < 0 )
551  return;
552 
553  QgsAttributeTableConfig config = mConfig;
554  int sourceCol = config.mapVisibleColumnToIndex( col );
555  if ( sourceCol >= 0 )
556  {
557  bool ok = false;
558  int width = QInputDialog::getInt( this, tr( "Set column width" ), tr( "Enter column width" ),
559  mTableView->columnWidth( col ),
560  0, 1000, 10, &ok );
561  if ( ok )
562  {
563  config.setColumnWidth( sourceCol, width );
564  mLayerCache->layer()->setAttributeTableConfig( config );
565  setAttributeTableConfig( config );
566  }
567  }
568 }
569 
570 void QgsDualView::autosizeColumn()
571 {
572  QAction* action = qobject_cast<QAction*>( sender() );
573  int col = action->data().toInt();
574  mTableView->resizeColumnToContents( col );
575 }
576 
577 void QgsDualView::modifySort()
578 {
579  QgsVectorLayer* layer = mLayerCache->layer();
580  if ( !layer )
581  return;
582 
583  QgsAttributeTableConfig config = mConfig;
584 
585  QDialog orderByDlg;
586  orderByDlg.setWindowTitle( tr( "Configure attribute table sort order" ) );
587  QDialogButtonBox* dialogButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
588  QGridLayout* layout = new QGridLayout();
589  connect( dialogButtonBox, SIGNAL( accepted() ), &orderByDlg, SLOT( accept() ) );
590  connect( dialogButtonBox, SIGNAL( rejected() ), &orderByDlg, SLOT( reject() ) );
591  orderByDlg.setLayout( layout );
592 
593  QGroupBox* sortingGroupBox = new QGroupBox();
594  sortingGroupBox->setTitle( tr( "Enable sorting order in attribute table" ) );
595  sortingGroupBox->setCheckable( true );
596  sortingGroupBox->setChecked( !sortExpression().isEmpty() );
597  layout->addWidget( sortingGroupBox );
598  sortingGroupBox->setLayout( new QGridLayout() );
599 
600  QgsExpressionBuilderWidget* expressionBuilder = new QgsExpressionBuilderWidget();
601  QgsExpressionContext context;
605  expressionBuilder->setExpressionContext( context );
606  expressionBuilder->setLayer( layer );
607  expressionBuilder->loadFieldNames();
608  expressionBuilder->loadRecent( "generic" );
609  expressionBuilder->setExpressionText( sortExpression().isEmpty() ? layer->displayExpression() : sortExpression() );
610 
611  sortingGroupBox->layout()->addWidget( expressionBuilder );
612 
613  layout->addWidget( dialogButtonBox );
614  if ( orderByDlg.exec() )
615  {
616  if ( sortingGroupBox->isChecked() )
617  {
618  setSortExpression( expressionBuilder->expressionText() );
619  config.setSortExpression( expressionBuilder->expressionText() );
620  }
621  else
622  {
624  config.setSortExpression( QString() );
625  }
626 
627  layer->setAttributeTableConfig( config );
628  mConfig = config;
629  }
630 }
631 
632 void QgsDualView::zoomToCurrentFeature()
633 {
634  QModelIndex currentIndex = mTableView->currentIndex();
635  if ( !currentIndex.isValid() )
636  {
637  return;
638  }
639 
640  QgsFeatureIds ids;
641  ids.insert( mFilterModel->rowToId( currentIndex ) );
642  QgsMapCanvas* canvas = mFilterModel->mapCanvas();
643  if ( canvas )
644  {
645  canvas->zoomToFeatureIds( mLayerCache->layer(), ids );
646  }
647 }
648 
649 void QgsDualView::previewExpressionChanged( const QString& expression )
650 {
651  mLayerCache->layer()->setDisplayExpression( expression );
652 }
653 
654 void QgsDualView::sortByPreviewExpression()
655 {
656  setSortExpression( mFeatureList->displayExpression() );
657 }
658 
659 void QgsDualView::featureFormAttributeChanged()
660 {
661  mFeatureList->setCurrentFeatureEdited( true );
662 }
663 
665 {
666  mFilterModel->setFilteredFeatures( filteredFeatures );
667 }
668 
670 {
671  mMasterModel->setRequest( request );
672 }
673 
675 {
676  mTableView->setFeatureSelectionManager( featureSelectionManager );
677  mFeatureList->setFeatureSelectionManager( featureSelectionManager );
678 
679  if ( mFeatureSelectionManager && mFeatureSelectionManager->parent() == this )
680  delete mFeatureSelectionManager;
681 
682  mFeatureSelectionManager = featureSelectionManager;
683 }
684 
686 {
687  mFilterModel->setAttributeTableConfig( config );
688  mTableView->setAttributeTableConfig( config );
689  mConfig = config;
690 }
691 
693 {
694  if ( sortExpression.isNull() )
695  mFilterModel->sort( -1 );
696  else
697  mFilterModel->sort( sortExpression );
698 }
699 
701 {
702  return mFilterModel->sortExpression();
703 }
704 
705 void QgsDualView::progress( int i, bool& cancel )
706 {
707  if ( !mProgressDlg )
708  {
709  mProgressDlg = new QProgressDialog( tr( "Loading features..." ), tr( "Abort" ), 0, 0, this );
710  mProgressDlg->setWindowTitle( tr( "Attribute table" ) );
711  mProgressDlg->setWindowModality( Qt::WindowModal );
712  mProgressDlg->show();
713  }
714 
715  mProgressDlg->setValue( i );
716  mProgressDlg->setLabelText( tr( "%1 features loaded." ).arg( i ) );
717 
719 
720  cancel = mProgressDlg && mProgressDlg->wasCanceled();
721 }
722 
723 void QgsDualView::finished()
724 {
725  delete mProgressDlg;
726  mProgressDlg = nullptr;
727 }
728 
729 /*
730  * QgsAttributeTableAction
731  */
732 
734 {
735  mDualView->masterModel()->executeAction( mAction, mFieldIdx );
736 }
737 
739 {
740  QgsFeatureIds editedIds;
741  editedIds << mDualView->masterModel()->rowToId( mFieldIdx.row() );
742  mDualView->setCurrentEditSelection( editedIds );
743  mDualView->setView( QgsDualView::AttributeEditor );
744 }
745 
746 /*
747  * QgsAttributeTableMapLayerAction
748  */
749 
751 {
752  mDualView->masterModel()->executeMapLayerAction( mAction, mFieldIdx );
753 }
QLayout * layout() const
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
Definition: qgsfield.cpp:429
void customContextMenuRequested(const QPoint &pos)
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
bool canConvert(Type t) const
void setRequest(const QgsFeatureRequest &request)
Set a request that will be used to fill this attribute table model.
QgsActionManager * actions()
Get all layer actions defined on this layer.
QgsFeatureId rowToId(const QModelIndex &row)
Returns the feature id for a given model index.
static unsigned index
void setFilterMode(QgsAttributeTableFilterModel::FilterMode filterMode)
Set the filter mode.
const QgsAction & at(int idx) const
Get the action at the specified index.
void setSortExpression(const QString &sortExpression)
Set the sort expression used for sorting.
void setWidget(QWidget *widget)
virtual void loadLayer()
Loads the layer into the model Preferably to be called, before using this model as source for any oth...
void setupUi(QWidget *widget)
void setAttributeTableConfig(const QgsAttributeTableConfig &config)
Set the attribute table configuration to control which fields are shown, in which order they are show...
QgsMapCanvas * mapCanvas() const
Returns the map canvas.
int size() const
Get the number of actions managed by this.
QIcon iconForField(int fieldIdx) const
Returns an icon corresponding to a field index, based on the field&#39;s type and source.
Definition: qgsfield.cpp:492
void setSelectedOnTop(bool selectedOnTop)
Changes the sort order of the features.
void filterExpressionSet(const QString &expression, QgsAttributeForm::FilterType type)
Is emitted when a filter expression is set using the view.
void setFilterMode(FilterMode filterMode)
Set the filter mode the filter will use.
void toggleSearchMode(bool enabled)
Toggles whether search mode should be enabled in the form.
void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
Set the feature selection model.
void addWidget(QWidget *widget, int row, int column, QFlags< Qt::AlignmentFlag > alignment)
void openConditionalStyles()
const QgsRectangle & filterRect() const
Get the rectangle from which features will be taken.
void setWindowModality(Qt::WindowModality windowModality)
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:439
QgsFields fields() const
Returns the list of fields of this layer.
This class contains context information for attribute editor widgets.
QObject * sender() const
int mapVisibleColumnToIndex(int visibleColumn) const
Maps a visible column index to its original column index.
QVariant data() const
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
void setLayer(QgsVectorLayer *layer)
Sets layer in order to get the fields and values.
void setLabelText(const QString &text)
bool save()
Save all the values from the editors to the layer.
ViewMode
The view modes, in which this widget can present information.
Definition: qgsdualview.h:55
const T & at(int i) const
void addAction(QAction *action)
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
T value() const
int exec()
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
QList< QgsMapLayerAction * > mapLayerActions(QgsMapLayer *layer, const QgsMapLayerAction::Targets &targets=QgsMapLayerAction::AllActions)
Returns the map layer actions which can run on the specified layer.
QgsVectorLayer * layer()
Returns the layer to which this cache belongs.
int filteredFeatureCount()
Returns the number of features which are currently visible, according to the filter restrictions...
const QPixmap * icon() const
void setDisplayExpression(const QString &displayExpression)
Set the preview expression, used to create a human readable preview string.
QString join(const QString &separator) const
const_iterator insert(const T &value)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
QString widgetType(int fieldIdx) const
Get the id for the editor widget used to represent the field at the given index.
A model backed by a QgsVectorLayerCache which is able to provide feature/attribute information to a Q...
void setCurrentEditSelection(const QgsFeatureIds &fids)
Set the current edit selection in the AttributeEditor mode.
QgsEditFormConfig * editFormConfig() const
Get the configuration of the form used to represent this vector layer.
const QString displayExpression()
Get the preview expression, used to create a human readable preview string.
virtual bool isEditable() const override
Returns true if the provider is in editing mode.
QString tr(const char *sourceText, const char *disambiguation, int n)
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:109
virtual int rowCount(const QModelIndex &parent) const
int x() const
void setView(ViewMode view)
Change the current view mode.
int size() const
bool isNull() const
virtual void setFilteredFeatures(const QgsFeatureIds &ids)
Specify a list of features, which the filter will accept.
virtual QVariant data(const QModelIndex &index, int role) const override
Returns data on the given index.
void setAttributeTableConfig(const QgsAttributeTableConfig &config)
Set the attribute table config which should be used to control the appearance of the attribute table...
QgsDualView(QWidget *parent=nullptr)
Constructor.
Definition: qgsdualview.cpp:39
Show a list of the features, where one can be chosen and the according attribute dialog will be prese...
Definition: qgsdualview.h:66
int width() const
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QgsVectorLayer * layer() const
Returns the layer this filter acts on.
void setMode(Mode mode)
Sets the current mode of the form.
int getInt(QWidget *parent, const QString &title, const QString &label, int value, int min, int max, int step, bool *ok, QFlags< Qt::WindowType > flags)
const char * name() const
void setValue(int progress)
bool isValid() const
void setColumnWidth(int column, int width)
Sets the width of a column.
void setMapping(QObject *sender, int id)
QString name() const
The name of the action. This may be a longer description.
Definition: qgsaction.h:97
void processEvents(QFlags< QEventLoop::ProcessEventsFlag > flags)
void append(const T &value)
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
void setChecked(bool checked)
void setLayout(QLayout *layout)
void popup(const QPoint &p, QAction *atAction)
int toInt(bool *ok) const
FilterType
Filter types.
QClipboard * clipboard()
void setExtraColumns(int extraColumns)
Empty extra columns to announce from this model.
void setFeature(const QgsFeature &feature)
Update all editors to correspond to a different feature.
FilterMode
The filter mode defines how the rows should be filtered.
/class QgsOrganizeTableColumnsDialog /ingroup gui Dialog for organising (hiding and reordering) colum...
virtual int capabilities() const
Returns a bitmask containing the supported capabilities Note, some capabilities may change depending ...
void setEditorContext(const QgsAttributeEditorContext &context)
Sets the context in which this table is shown.
QString name() const
Gets the name of the field.
Definition: qgsfield.cpp:84
Utility class that encapsulates an action based on vector attributes.
Definition: qgsaction.h:25
bool isEmpty() const
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
bool isEmpty() const
ViewMode view() const
Returns the current view mode.
void setCurrentIndex(int index)
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void init(QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request=QgsFeatureRequest(), const QgsAttributeEditorContext &context=QgsAttributeEditorContext())
Has to be called to initialize the dual view.
Definition: qgsdualview.cpp:70
QgsFeatureIds filteredFeatures()
Get a list of currently visible feature ids.
Definition: qgsdualview.h:149
const QString displayField() const
Returns the primary display field name used in the identify results dialog.
void filterChanged()
Is emitted, whenever the filter changes.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
void loadFieldNames()
Loads all the field names from the layer.
QAction * addSeparator()
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:44
void hide()
Fast access to features using their ID.
void addWidget(QWidget *w)
void setData(const QVariant &userData)
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context for the widget.
iterator end()
void setWidgetResizable(bool resizable)
This class caches features of a given QgsVectorLayer.
QgsAttributeTableModel * masterModel() const
Returns the model which has the information about all features (not only filtered) ...
Definition: qgsdualview.h:156
bool saveEditChanges()
saveEditChanges
void setRequest(const QgsFeatureRequest &request)
Set the request.
QgsAttributeTableFilterModel::FilterMode filterMode()
Get the filter mode.
Definition: qgsdualview.h:113
QgsAttributeList pkAttributeList() const
Returns list of attributes making up the primary key.
A reusable widget that can be used to build a expression string.
void setSelectedOnTop(bool selectedOnTop)
Toggle the selectedOnTop flag.
QVariant value(const QString &key, const QVariant &defaultValue) const
void zoomToFeatureIds(QgsVectorLayer *layer, const QgsFeatureIds &ids)
Set canvas extent to the bounding box of a set of features.
static QgsMapLayerActionRegistry * instance()
Returns the instance pointer, creating the object on the first call.
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of rows.
void setCacheGeometry(bool cacheGeometry)
Enable or disable the caching of geometries.
void setFullCache(bool fullCache)
This enables or disables full caching.
virtual void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
Sort by the given column using the given order.
QString sortExpression() const
The expression which is used to sort the attribute table.
void setTitle(const QString &title)
void setCheckable(bool checkable)
void setColumnHidden(int column, bool hidden)
Sets whether the specified column should be hidden.
void setWindowTitle(const QString &)
void displayExpressionChanged(const QString &expression)
Is emitted, whenever the display expression is successfully changed.
QgsFeatureId idxToFid(const QModelIndex &index) const
QString expressionText()
Gets the expression string that has been set in the expression area.
void formModeChanged(QgsAttributeForm::Mode mode)
Emitted when the form changes mode.
QString sortExpression() const
Get the expression used for sorting the table and feature list.
void setExpressionText(const QString &expression)
Sets the expression string for the widget.
const QgsAttributeEditorContext * parentContext() const
bool isValid() const
bool runable() const
Checks if the action is runable on the current platform.
Definition: qgsaction.cpp:19
StandardButton warning(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
void setText(const QString &text, Mode mode)
void show()
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
QgsVectorDataProvider * dataProvider()
Returns the data provider.
void setFilteredFeatures(const QgsFeatureIds &filteredFeatures)
Set a list of currently visible features.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
This is a container for configuration of the attribute table.
void setMultiEditEnabled(bool enabled)
Sets whether multi edit mode is enabled.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Is an interface class to abstract feature selection handling.
void copyCellContent() const
Copy the content of the selected cell in the clipboard.
QObject * parent() const
Represents a vector layer which manages a vector based data sets.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
void setAttributeTableConfig(const QgsAttributeTableConfig &attributeTableConfig)
Set the attribute table configuration object.
iterator begin()
A generic dialog for building expression strings.
void setEnabled(bool)
void columnBoxInit()
Initializes widgets which depend on the attributes of this layer.
int featureCount()
Returns the number of features on the layer.
void setSortExpression(const QString &sortExpression)
Set the expression used for sorting the table and feature list.