void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context ) { mEditorContext = context; connect( mTableView, SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) ); initLayerCache( layer, !request.filterRect().isNull() ); initModels( mapCanvas, request ); mConditionalFormatWidget->setLayer( layer ); mTableView->setModel( mFilterModel ); mFeatureList->setModel( mFeatureListModel ); mAttributeForm = new QgsAttributeForm( layer, QgsFeature(), mEditorContext ); if ( !mAttributeEditorScrollArea->layout() ) mAttributeEditorScrollArea->setLayout( new QGridLayout() ); mAttributeEditorScrollArea->layout()->addWidget( mAttributeForm ); mAttributeEditorScrollArea->setWidget( mAttributeForm ); mAttributeForm->hideButtonBox(); connect( mAttributeForm, SIGNAL( attributeChanged( QString, QVariant ) ), this, SLOT( featureFormAttributeChanged() ) ); connect( mMasterModel, SIGNAL( modelChanged() ), mAttributeForm, SLOT( refreshFeature() ) ); if ( mFeatureListPreviewButton->defaultAction() ) mFeatureList->setDisplayExpression( mDisplayExpression ); else columnBoxInit(); // This slows down load of the attribute table heaps and uses loads of memory. //mTableView->resizeColumnsToContents(); mFeatureList->setEditSelection( QgsFeatureIds() << mFeatureListModel->idxToFid( mFeatureListModel->index( 0, 0 ) ) ); }
void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest &request, QgsAttributeEditorContext context ) { mEditorContext = context; connect( mTableView, SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) ); initLayerCache( layer ); initModels( mapCanvas, request ); mTableView->setModel( mFilterModel ); mFeatureList->setModel( mFeatureListModel ); mAttributeForm = new QgsAttributeForm( layer, QgsFeature(), mEditorContext ); mAttributeEditorScrollArea->setLayout( new QGridLayout() ); mAttributeEditorScrollArea->layout()->addWidget( mAttributeForm ); mAttributeEditorScrollArea->setWidget( mAttributeForm ); mAttributeForm->hideButtonBox(); connect( mAttributeForm, SIGNAL( attributeChanged( QString, QVariant ) ), this, SLOT( featureFormAttributeChanged() ) ); if ( mFeatureListPreviewButton->defaultAction() ) mFeatureList->setDisplayExpression( mDisplayExpression ); else columnBoxInit(); mFeatureList->setEditSelection( QgsFeatureIds() << mFeatureListModel->idxToFid( mFeatureListModel->index( 0, 0 ) ) ); }
void QgsDualView::init( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context, bool loadFeatures ) { if ( !layer ) return; mLayer = layer; mEditorContext = context; connect( mTableView, &QgsAttributeTableView::willShowContextMenu, this, &QgsDualView::viewWillShowContextMenu ); mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu ); connect( mTableView->horizontalHeader(), &QHeaderView::customContextMenuRequested, this, &QgsDualView::showViewHeaderMenu ); connect( mTableView, &QgsAttributeTableView::columnResized, this, &QgsDualView::tableColumnResized ); connect( mFeatureList, &QgsFeatureListView::willShowContextMenu, this, &QgsDualView::widgetWillShowContextMenu ); initLayerCache( !( request.flags() & QgsFeatureRequest::NoGeometry ) || !request.filterRect().isNull() ); initModels( mapCanvas, request, loadFeatures ); mConditionalFormatWidget->setLayer( mLayer ); mTableView->setModel( mFilterModel ); mFeatureList->setModel( mFeatureListModel ); delete mAttributeForm; mAttributeForm = new QgsAttributeForm( mLayer, mTempAttributeFormFeature, mEditorContext ); mTempAttributeFormFeature = QgsFeature(); if ( !context.parentContext() ) { mAttributeEditorScrollArea = new QgsScrollArea(); mAttributeEditorScrollArea->setWidgetResizable( true ); mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea ); mAttributeEditorScrollArea->setWidget( mAttributeForm ); } else { mAttributeEditor->layout()->addWidget( mAttributeForm ); } connect( mAttributeForm, &QgsAttributeForm::widgetValueChanged, this, &QgsDualView::featureFormAttributeChanged ); connect( mAttributeForm, &QgsAttributeForm::modeChanged, this, &QgsDualView::formModeChanged ); connect( mMasterModel, &QgsAttributeTableModel::modelChanged, mAttributeForm, &QgsAttributeForm::refreshFeature ); connect( mAttributeForm, &QgsAttributeForm::filterExpressionSet, this, &QgsDualView::filterExpressionSet ); connect( mFilterModel, &QgsAttributeTableFilterModel::sortColumnChanged, this, &QgsDualView::onSortColumnChanged ); if ( mFeatureListPreviewButton->defaultAction() ) mFeatureList->setDisplayExpression( mDisplayExpression ); else columnBoxInit(); // This slows down load of the attribute table heaps and uses loads of memory. //mTableView->resizeColumnsToContents(); mFeatureList->setEditSelection( QgsFeatureIds() << mFeatureListModel->idxToFid( mFeatureListModel->index( 0, 0 ) ) ); }
void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context ) { if ( !layer ) return; mEditorContext = context; connect( mTableView, SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) ); mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu ); connect( mTableView->horizontalHeader(), SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( showViewHeaderMenu( QPoint ) ) ); connect( mTableView, SIGNAL( columnResized( int, int ) ), this, SLOT( tableColumnResized( int, int ) ) ); initLayerCache( layer, !request.filterRect().isNull() ); initModels( mapCanvas, request ); mConditionalFormatWidget->setLayer( layer ); mTableView->setModel( mFilterModel ); mFeatureList->setModel( mFeatureListModel ); delete mAttributeForm; mAttributeForm = new QgsAttributeForm( layer, QgsFeature(), mEditorContext ); if ( !context.parentContext() ) { mAttributeEditorScrollArea = new QScrollArea(); mAttributeEditorScrollArea->setWidgetResizable( true ); mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea ); mAttributeEditorScrollArea->setWidget( mAttributeForm ); } else { mAttributeEditor->layout()->addWidget( mAttributeForm ); } connect( mAttributeForm, SIGNAL( attributeChanged( QString, QVariant ) ), this, SLOT( featureFormAttributeChanged() ) ); connect( mAttributeForm, SIGNAL( modeChanged( QgsAttributeForm::Mode ) ), this, SIGNAL( formModeChanged( QgsAttributeForm::Mode ) ) ); connect( mMasterModel, SIGNAL( modelChanged() ), mAttributeForm, SLOT( refreshFeature() ) ); connect( mAttributeForm, SIGNAL( filterExpressionSet( QString, QgsAttributeForm::FilterType ) ), this, SIGNAL( filterExpressionSet( QString, QgsAttributeForm::FilterType ) ) ); connect( mFilterModel, SIGNAL( sortColumnChanged( int, Qt::SortOrder ) ), this, SLOT( onSortColumnChanged() ) ); if ( mFeatureListPreviewButton->defaultAction() ) mFeatureList->setDisplayExpression( mDisplayExpression ); else columnBoxInit(); // This slows down load of the attribute table heaps and uses loads of memory. //mTableView->resizeColumnsToContents(); mFeatureList->setEditSelection( QgsFeatureIds() << mFeatureListModel->idxToFid( mFeatureListModel->index( 0, 0 ) ) ); }
void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest &request, QgsAttributeEditorContext context ) { mEditorContext = context; connect( mTableView, SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) ); initLayerCache( layer ); initModels( mapCanvas, request ); mTableView->setModel( mFilterModel ); mFeatureList->setModel( mFeatureListModel ); mAttributeDialog = new QgsAttributeDialog( layer, NULL, false, NULL, true, mEditorContext ); if ( mAttributeDialog->dialog() ) mAttributeEditorLayout->addWidget( mAttributeDialog->dialog() ); columnBoxInit(); }
void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, QgsDistanceArea myDa ) { mDistanceArea = myDa; connect( mTableView, SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) ); connect( layer, SIGNAL( editingStarted() ), this, SLOT( editingToggled() ) ); connect( layer, SIGNAL( beforeCommitChanges() ), this, SLOT( editingToggled() ) ); initLayerCache( layer ); initModels( mapCanvas ); mTableView->setModel( mFilterModel ); mFeatureList->setModel( mFeatureListModel ); mAttributeDialog = new QgsAttributeDialog( layer, 0, false, myDa ); if ( mAttributeDialog->dialog() ) mAttributeEditorLayout->addWidget( mAttributeDialog->dialog() ); columnBoxInit(); }
QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWidget *parent, Qt::WindowFlags flags ) : QDialog( parent, flags ), mDock( NULL ) { mLayer = theLayer; setupUi( this ); setAttribute( Qt::WA_DeleteOnClose ); QSettings settings; restoreGeometry( settings.value( "/Windows/BetterAttributeTable/geometry" ).toByteArray() ); mView->setLayer( mLayer ); mFilterModel = ( QgsAttributeTableFilterModel * ) mView->model(); mModel = ( QgsAttributeTableModel * )(( QgsAttributeTableFilterModel * )mView->model() )->sourceModel(); mQuery = query; mColumnBox = columnBox; columnBoxInit(); bool myDockFlag = settings.value( "/qgis/dockAttributeTable", false ).toBool(); if ( myDockFlag ) { mDock = new QgsAttributeTableDock( tr( "Attribute table - %1 (%n Feature(s))", "feature count", mModel->rowCount() ).arg( mLayer->name() ), QgisApp::instance() ); mDock->setAllowedAreas( Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea ); mDock->setWidget( this ); connect( this, SIGNAL( destroyed() ), mDock, SLOT( close() ) ); QgisApp::instance()->addDockWidget( Qt::BottomDockWidgetArea, mDock ); } updateTitle(); mRemoveSelectionButton->setIcon( QgisApp::getThemeIcon( "/mActionUnselectAttributes.png" ) ); mSelectedToTopButton->setIcon( QgisApp::getThemeIcon( "/mActionSelectedToTop.png" ) ); mCopySelectedRowsButton->setIcon( QgisApp::getThemeIcon( "/mActionCopySelected.png" ) ); mZoomMapToSelectedRowsButton->setIcon( QgisApp::getThemeIcon( "/mActionZoomToSelected.png" ) ); mInvertSelectionButton->setIcon( QgisApp::getThemeIcon( "/mActionInvertSelection.png" ) ); mToggleEditingButton->setIcon( QgisApp::getThemeIcon( "/mActionToggleEditing.png" ) ); mSaveEditsButton->setIcon( QgisApp::getThemeIcon( "/mActionSaveEdits.png" ) ); mDeleteSelectedButton->setIcon( QgisApp::getThemeIcon( "/mActionDeleteSelected.png" ) ); mOpenFieldCalculator->setIcon( QgisApp::getThemeIcon( "/mActionCalculateField.png" ) ); mAddAttribute->setIcon( QgisApp::getThemeIcon( "/mActionNewAttribute.png" ) ); mRemoveAttribute->setIcon( QgisApp::getThemeIcon( "/mActionDeleteAttribute.png" ) ); // toggle editing bool canChangeAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues; bool canDeleteFeatures = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteFeatures; bool canAddAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::AddAttributes; bool canDeleteAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteAttributes; bool canAddFeatures = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures; mToggleEditingButton->setCheckable( true ); mToggleEditingButton->setChecked( mLayer->isEditable() ); mToggleEditingButton->setEnabled( canChangeAttributes && !mLayer->isReadOnly() ); mSaveEditsButton->setEnabled( canChangeAttributes && mLayer->isEditable() ); mOpenFieldCalculator->setEnabled( canChangeAttributes && mLayer->isEditable() ); mDeleteSelectedButton->setEnabled( canDeleteFeatures && mLayer->isEditable() ); mAddAttribute->setEnabled( canAddAttributes && mLayer->isEditable() ); mRemoveAttribute->setEnabled( canDeleteAttributes && mLayer->isEditable() ); mAddFeature->setEnabled( canAddFeatures && mLayer->isEditable() && mLayer->geometryType() == QGis::NoGeometry ); mAddFeature->setHidden( !canAddFeatures || mLayer->geometryType() != QGis::NoGeometry ); // info from table to application connect( this, SIGNAL( editingToggled( QgsMapLayer * ) ), QgisApp::instance(), SLOT( toggleEditing( QgsMapLayer * ) ) ); connect( this, SIGNAL( saveEdits( QgsMapLayer * ) ), QgisApp::instance(), SLOT( saveEdits( QgsMapLayer * ) ) ); // info from layer to table connect( mLayer, SIGNAL( editingStarted() ), this, SLOT( editingToggled() ) ); connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) ); connect( searchButton, SIGNAL( clicked() ), this, SLOT( search() ) ); connect( mAddFeature, SIGNAL( clicked() ), this, SLOT( addFeature() ) ); connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) ); connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( close() ) ); connect( mView->verticalHeader(), SIGNAL( sectionClicked( int ) ), this, SLOT( updateRowSelection( int ) ) ); connect( mView->verticalHeader(), SIGNAL( sectionPressed( int ) ), this, SLOT( updateRowPressed( int ) ) ); connect( mModel, SIGNAL( modelChanged() ), this, SLOT( updateSelection() ) ); if ( settings.value( "/qgis/attributeTableBehaviour", 0 ).toInt() == 2 ) { connect( QgisApp::instance()->mapCanvas(), SIGNAL( extentsChanged() ), mModel, SLOT( layerModified() ) ); } mLastClickedHeaderIndex = 0; mSelectionModel = new QItemSelectionModel( mFilterModel ); updateSelectionFromLayer(); //make sure to show all recs on first load on_cbxShowSelectedOnly_toggled( false ); }
QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWidget *parent, Qt::WindowFlags flags ) : QDialog( parent, flags ) , mDock( nullptr ) , mLayer( theLayer ) , mRubberBand( nullptr ) , mCurrentSearchWidgetWrapper( nullptr ) { setupUi( this ); // Fix selection color on loosing focus (Windows) setStyleSheet( QgisApp::instance()->styleSheet() ); setAttribute( Qt::WA_DeleteOnClose ); QSettings settings; // Initialize the window geometry restoreGeometry( settings.value( "/Windows/BetterAttributeTable/geometry" ).toByteArray() ); QgsAttributeEditorContext context; myDa = new QgsDistanceArea(); myDa->setSourceCrs( mLayer->crs() ); myDa->setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() ); myDa->setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) ); context.setDistanceArea( *myDa ); context.setVectorLayerTools( QgisApp::instance()->vectorLayerTools() ); QgsFeatureRequest r; if ( mLayer->geometryType() != QGis::NoGeometry && settings.value( "/qgis/attributeTableBehaviour", QgsAttributeTableFilterModel::ShowAll ).toInt() == QgsAttributeTableFilterModel::ShowVisible ) { QgsMapCanvas *mc = QgisApp::instance()->mapCanvas(); QgsRectangle extent( mc->mapSettings().mapToLayerCoordinates( theLayer, mc->extent() ) ); r.setFilterRect( extent ); QgsGeometry *g = QgsGeometry::fromRect( extent ); mRubberBand = new QgsRubberBand( mc, QGis::Polygon ); mRubberBand->setToGeometry( g, theLayer ); delete g; mActionShowAllFilter->setText( tr( "Show All Features In Initial Canvas Extent" ) ); } // Initialize dual view mMainView->init( mLayer, QgisApp::instance()->mapCanvas(), r, context ); // Initialize filter gui elements mFilterActionMapper = new QSignalMapper( this ); mFilterColumnsMenu = new QMenu( this ); mActionFilterColumnsMenu->setMenu( mFilterColumnsMenu ); mApplyFilterButton->setDefaultAction( mActionApplyFilter ); // Set filter icon in a couple of places QIcon filterIcon = QgsApplication::getThemeIcon( "/mActionFilter.svg" ); mActionShowAllFilter->setIcon( filterIcon ); mActionAdvancedFilter->setIcon( filterIcon ); mActionSelectedFilter->setIcon( filterIcon ); mActionVisibleFilter->setIcon( filterIcon ); mActionEditedFilter->setIcon( filterIcon ); // Connect filter signals connect( mActionAdvancedFilter, SIGNAL( triggered() ), SLOT( filterExpressionBuilder() ) ); connect( mActionShowAllFilter, SIGNAL( triggered() ), SLOT( filterShowAll() ) ); connect( mActionSelectedFilter, SIGNAL( triggered() ), SLOT( filterSelected() ) ); connect( mActionVisibleFilter, SIGNAL( triggered() ), SLOT( filterVisible() ) ); connect( mActionEditedFilter, SIGNAL( triggered() ), SLOT( filterEdited() ) ); connect( mFilterActionMapper, SIGNAL( mapped( QObject* ) ), SLOT( filterColumnChanged( QObject* ) ) ); connect( mFilterQuery, SIGNAL( returnPressed() ), SLOT( filterQueryAccepted() ) ); connect( mActionApplyFilter, SIGNAL( triggered() ), SLOT( filterQueryAccepted() ) ); connect( mSetStyles, SIGNAL( pressed() ), SLOT( openConditionalStyles() ) ); // info from layer to table connect( mLayer, SIGNAL( editingStarted() ), this, SLOT( editingToggled() ) ); connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) ); connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( close() ) ); connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateTitle() ) ); connect( mLayer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SLOT( updateTitle() ) ); connect( mLayer, SIGNAL( featuresDeleted( QgsFeatureIds ) ), this, SLOT( updateTitle() ) ); connect( mLayer, SIGNAL( attributeAdded( int ) ), this, SLOT( columnBoxInit() ) ); connect( mLayer, SIGNAL( attributeDeleted( int ) ), this, SLOT( columnBoxInit() ) ); // connect table info to window connect( mMainView, SIGNAL( filterChanged() ), this, SLOT( updateTitle() ) ); // info from table to application connect( this, SIGNAL( saveEdits( QgsMapLayer * ) ), QgisApp::instance(), SLOT( saveEdits( QgsMapLayer * ) ) ); bool myDockFlag = settings.value( "/qgis/dockAttributeTable", false ).toBool(); if ( myDockFlag ) { mDock = new QgsAttributeTableDock( tr( "Attribute table - %1 (%n Feature(s))", "feature count", mMainView->featureCount() ).arg( mLayer->name() ), QgisApp::instance() ); mDock->setAllowedAreas( Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea ); mDock->setWidget( this ); connect( this, SIGNAL( destroyed() ), mDock, SLOT( close() ) ); QgisApp::instance()->addDockWidget( Qt::BottomDockWidgetArea, mDock ); } columnBoxInit(); updateTitle(); mRemoveSelectionButton->setIcon( QgsApplication::getThemeIcon( "/mActionUnselectAttributes.png" ) ); mSelectedToTopButton->setIcon( QgsApplication::getThemeIcon( "/mActionSelectedToTop.png" ) ); mCopySelectedRowsButton->setIcon( QgsApplication::getThemeIcon( "/mActionCopySelected.png" ) ); mZoomMapToSelectedRowsButton->setIcon( QgsApplication::getThemeIcon( "/mActionZoomToSelected.svg" ) ); mPanMapToSelectedRowsButton->setIcon( QgsApplication::getThemeIcon( "/mActionPanToSelected.svg" ) ); mInvertSelectionButton->setIcon( QgsApplication::getThemeIcon( "/mActionInvertSelection.png" ) ); mToggleEditingButton->setIcon( QgsApplication::getThemeIcon( "/mActionToggleEditing.svg" ) ); mSaveEditsButton->setIcon( QgsApplication::getThemeIcon( "/mActionSaveEdits.svg" ) ); mDeleteSelectedButton->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteSelected.svg" ) ); mOpenFieldCalculator->setIcon( QgsApplication::getThemeIcon( "/mActionCalculateField.png" ) ); mAddAttribute->setIcon( QgsApplication::getThemeIcon( "/mActionNewAttribute.png" ) ); mRemoveAttribute->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteAttribute.png" ) ); mTableViewButton->setIcon( QgsApplication::getThemeIcon( "/mActionOpenTable.png" ) ); mAttributeViewButton->setIcon( QgsApplication::getThemeIcon( "/mActionPropertyItem.png" ) ); mExpressionSelectButton->setIcon( QgsApplication::getThemeIcon( "/mIconExpressionSelect.svg" ) ); mAddFeature->setIcon( QgsApplication::getThemeIcon( "/mActionNewTableRow.png" ) ); // toggle editing bool canChangeAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues; bool canDeleteFeatures = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteFeatures; bool canAddAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::AddAttributes; bool canDeleteAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteAttributes; bool canAddFeatures = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures; mToggleEditingButton->blockSignals( true ); mToggleEditingButton->setCheckable( true ); mToggleEditingButton->setChecked( mLayer->isEditable() ); mToggleEditingButton->setEnabled(( canChangeAttributes || canDeleteFeatures || canAddAttributes || canDeleteAttributes || canAddFeatures ) && !mLayer->isReadOnly() ); mToggleEditingButton->blockSignals( false ); mSaveEditsButton->setEnabled( mToggleEditingButton->isEnabled() && mLayer->isEditable() ); mReloadButton->setEnabled( ! mLayer->isEditable() ); mAddAttribute->setEnabled(( canChangeAttributes || canAddAttributes ) && mLayer->isEditable() ); mDeleteSelectedButton->setEnabled( canDeleteFeatures && mLayer->isEditable() ); mAddFeature->setEnabled( canAddFeatures && mLayer->isEditable() ); mAddFeature->setHidden( !canAddFeatures ); mMainViewButtonGroup->setId( mTableViewButton, QgsDualView::AttributeTable ); mMainViewButtonGroup->setId( mAttributeViewButton, QgsDualView::AttributeEditor ); // Load default attribute table filter QgsAttributeTableFilterModel::FilterMode defaultFilterMode = ( QgsAttributeTableFilterModel::FilterMode ) settings.value( "/qgis/attributeTableBehaviour", QgsAttributeTableFilterModel::ShowAll ).toInt(); switch ( defaultFilterMode ) { case QgsAttributeTableFilterModel::ShowVisible: filterVisible(); break; case QgsAttributeTableFilterModel::ShowSelected: filterSelected(); break; case QgsAttributeTableFilterModel::ShowAll: default: filterShowAll(); break; } mUpdateExpressionText->registerGetExpressionContextCallback( &_getExpressionContext, mLayer ); mFieldModel = new QgsFieldModel( this ); mFieldModel->setLayer( mLayer ); mFieldCombo->setModel( mFieldModel ); connect( mRunFieldCalc, SIGNAL( clicked() ), this, SLOT( updateFieldFromExpression() ) ); connect( mRunFieldCalcSelected, SIGNAL( clicked() ), this, SLOT( updateFieldFromExpressionSelected() ) ); // NW TODO Fix in 2.6 - Doesn't work with field model for some reason. // connect( mUpdateExpressionText, SIGNAL( returnPressed() ), this, SLOT( updateFieldFromExpression() ) ); connect( mUpdateExpressionText, SIGNAL( fieldChanged( QString, bool ) ), this, SLOT( updateButtonStatus( QString, bool ) ) ); mUpdateExpressionText->setLayer( mLayer ); mUpdateExpressionText->setLeftHandButtonStyle( true ); mMainView->setView( QgsDualView::AttributeTable ); editingToggled(); }
QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWidget *parent, Qt::WindowFlags flags ) : QDialog( parent, flags ) , mDock( nullptr ) , mLayer( theLayer ) , mRubberBand( nullptr ) , mCurrentSearchWidgetWrapper( nullptr ) { setupUi( this ); Q_FOREACH ( const QgsField& field, mLayer->fields() ) { mVisibleFields.append( field.name() ); } // Fix selection color on loosing focus (Windows) setStyleSheet( QgisApp::instance()->styleSheet() ); setAttribute( Qt::WA_DeleteOnClose ); layout()->setMargin( 0 ); layout()->setContentsMargins( 0, 0, 0, 0 ); static_cast< QGridLayout* >( layout() )->setVerticalSpacing( 0 ); QSettings settings; int size = settings.value( "/IconSize", 16 ).toInt(); if ( size > 32 ) { size -= 16; } else if ( size == 32 ) { size = 24; } else { size = 16; } mToolbar->setIconSize( QSize( size, size ) ); // Initialize the window geometry restoreGeometry( settings.value( "/Windows/BetterAttributeTable/geometry" ).toByteArray() ); myDa = new QgsDistanceArea(); myDa->setSourceCrs( mLayer->crs() ); myDa->setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() ); myDa->setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) ); mEditorContext.setDistanceArea( *myDa ); mEditorContext.setVectorLayerTools( QgisApp::instance()->vectorLayerTools() ); QgsFeatureRequest r; if ( mLayer->geometryType() != QGis::NoGeometry && settings.value( "/qgis/attributeTableBehaviour", QgsAttributeTableFilterModel::ShowAll ).toInt() == QgsAttributeTableFilterModel::ShowVisible ) { QgsMapCanvas *mc = QgisApp::instance()->mapCanvas(); QgsRectangle extent( mc->mapSettings().mapToLayerCoordinates( theLayer, mc->extent() ) ); r.setFilterRect( extent ); QgsGeometry *g = QgsGeometry::fromRect( extent ); mRubberBand = new QgsRubberBand( mc, QGis::Polygon ); mRubberBand->setToGeometry( g, theLayer ); delete g; mActionShowAllFilter->setText( tr( "Show All Features In Initial Canvas Extent" ) ); } // Initialize dual view mMainView->init( mLayer, QgisApp::instance()->mapCanvas(), r, mEditorContext ); QgsAttributeTableConfig config = mLayer->attributeTableConfig(); mMainView->setAttributeTableConfig( config ); // Initialize filter gui elements mFilterActionMapper = new QSignalMapper( this ); mFilterColumnsMenu = new QMenu( this ); mActionFilterColumnsMenu->setMenu( mFilterColumnsMenu ); mApplyFilterButton->setDefaultAction( mActionApplyFilter ); // Set filter icon in a couple of places QIcon filterIcon = QgsApplication::getThemeIcon( "/mActionFilter2.svg" ); mActionShowAllFilter->setIcon( filterIcon ); mActionAdvancedFilter->setIcon( filterIcon ); mActionSelectedFilter->setIcon( filterIcon ); mActionVisibleFilter->setIcon( filterIcon ); mActionEditedFilter->setIcon( filterIcon ); // Connect filter signals connect( mActionAdvancedFilter, SIGNAL( triggered() ), SLOT( filterExpressionBuilder() ) ); connect( mActionShowAllFilter, SIGNAL( triggered() ), SLOT( filterShowAll() ) ); connect( mActionSelectedFilter, SIGNAL( triggered() ), SLOT( filterSelected() ) ); connect( mActionVisibleFilter, SIGNAL( triggered() ), SLOT( filterVisible() ) ); connect( mActionEditedFilter, SIGNAL( triggered() ), SLOT( filterEdited() ) ); connect( mFilterActionMapper, SIGNAL( mapped( QObject* ) ), SLOT( filterColumnChanged( QObject* ) ) ); connect( mFilterQuery, SIGNAL( returnPressed() ), SLOT( filterQueryAccepted() ) ); connect( mActionApplyFilter, SIGNAL( triggered() ), SLOT( filterQueryAccepted() ) ); connect( mActionSetStyles, SIGNAL( triggered() ), SLOT( openConditionalStyles() ) ); // info from layer to table connect( mLayer, SIGNAL( editingStarted() ), this, SLOT( editingToggled() ) ); connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) ); connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( close() ) ); connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateTitle() ) ); connect( mLayer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SLOT( updateTitle() ) ); connect( mLayer, SIGNAL( featuresDeleted( QgsFeatureIds ) ), this, SLOT( updateTitle() ) ); connect( mLayer, SIGNAL( attributeAdded( int ) ), this, SLOT( columnBoxInit() ) ); connect( mLayer, SIGNAL( attributeDeleted( int ) ), this, SLOT( columnBoxInit() ) ); // connect table info to window connect( mMainView, SIGNAL( filterChanged() ), this, SLOT( updateTitle() ) ); connect( mMainView, SIGNAL( filterExpressionSet( QString, QgsAttributeForm::FilterType ) ), this, SLOT( formFilterSet( QString, QgsAttributeForm::FilterType ) ) ); connect( mMainView, SIGNAL( formModeChanged( QgsAttributeForm::Mode ) ), this, SLOT( viewModeChanged( QgsAttributeForm::Mode ) ) ); // info from table to application connect( this, SIGNAL( saveEdits( QgsMapLayer * ) ), QgisApp::instance(), SLOT( saveEdits( QgsMapLayer * ) ) ); bool myDockFlag = settings.value( "/qgis/dockAttributeTable", false ).toBool(); if ( myDockFlag ) { mDock = new QgsAttributeTableDock( tr( "%1 (%n Feature(s))", "feature count", mMainView->featureCount() ).arg( mLayer->name() ), QgisApp::instance() ); mDock->setWidget( this ); connect( this, SIGNAL( destroyed() ), mDock, SLOT( close() ) ); QgisApp::instance()->addDockWidget( Qt::BottomDockWidgetArea, mDock ); } columnBoxInit(); updateTitle(); mActionRemoveSelection->setIcon( QgsApplication::getThemeIcon( "/mActionDeselectAll.svg" ) ); mActionSelectAll->setIcon( QgsApplication::getThemeIcon( "/mActionSelectAll.svg" ) ); mActionSelectedToTop->setIcon( QgsApplication::getThemeIcon( "/mActionSelectedToTop.svg" ) ); mActionCopySelectedRows->setIcon( QgsApplication::getThemeIcon( "/mActionEditCopy.svg" ) ); mActionPasteFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionEditPaste.svg" ) ); mActionZoomMapToSelectedRows->setIcon( QgsApplication::getThemeIcon( "/mActionZoomToSelected.svg" ) ); mActionPanMapToSelectedRows->setIcon( QgsApplication::getThemeIcon( "/mActionPanToSelected.svg" ) ); mActionInvertSelection->setIcon( QgsApplication::getThemeIcon( "/mActionInvertSelection.svg" ) ); mActionToggleEditing->setIcon( QgsApplication::getThemeIcon( "/mActionToggleEditing.svg" ) ); mActionSaveEdits->setIcon( QgsApplication::getThemeIcon( "/mActionSaveEdits.svg" ) ); mActionDeleteSelected->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteSelected.svg" ) ); mActionOpenFieldCalculator->setIcon( QgsApplication::getThemeIcon( "/mActionCalculateField.svg" ) ); mActionAddAttribute->setIcon( QgsApplication::getThemeIcon( "/mActionNewAttribute.svg" ) ); mActionRemoveAttribute->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteAttribute.svg" ) ); mTableViewButton->setIcon( QgsApplication::getThemeIcon( "/mActionOpenTable.svg" ) ); mAttributeViewButton->setIcon( QgsApplication::getThemeIcon( "/mActionFormView.svg" ) ); mActionExpressionSelect->setIcon( QgsApplication::getThemeIcon( "/mIconExpressionSelect.svg" ) ); mActionAddFeature->setIcon( QgsApplication::getThemeIcon( "/mActionNewTableRow.svg" ) ); // toggle editing bool canChangeAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues; bool canDeleteFeatures = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteFeatures; bool canAddAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::AddAttributes; bool canDeleteAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteAttributes; bool canAddFeatures = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures; mActionToggleEditing->blockSignals( true ); mActionToggleEditing->setCheckable( true ); mActionToggleEditing->setChecked( mLayer->isEditable() ); mActionToggleEditing->setEnabled(( canChangeAttributes || canDeleteFeatures || canAddAttributes || canDeleteAttributes || canAddFeatures ) && !mLayer->readOnly() ); mActionToggleEditing->blockSignals( false ); mActionSaveEdits->setEnabled( mActionToggleEditing->isEnabled() && mLayer->isEditable() ); mActionReload->setEnabled( ! mLayer->isEditable() ); mActionAddAttribute->setEnabled(( canChangeAttributes || canAddAttributes ) && mLayer->isEditable() ); mActionRemoveAttribute->setEnabled( canDeleteAttributes && mLayer->isEditable() ); mActionDeleteSelected->setEnabled( canDeleteFeatures && mLayer->isEditable() ); if ( !canDeleteFeatures ) mToolbar->removeAction( mActionDeleteSelected ); mActionAddFeature->setEnabled( canAddFeatures && mLayer->isEditable() ); if ( !canAddFeatures ) mToolbar->removeAction( mActionAddFeature ); if ( canDeleteFeatures || canAddFeatures ) mToolbar->insertSeparator( mActionExpressionSelect ); mMainViewButtonGroup->setId( mTableViewButton, QgsDualView::AttributeTable ); mMainViewButtonGroup->setId( mAttributeViewButton, QgsDualView::AttributeEditor ); // Load default attribute table filter QgsAttributeTableFilterModel::FilterMode defaultFilterMode = ( QgsAttributeTableFilterModel::FilterMode ) settings.value( "/qgis/attributeTableBehaviour", QgsAttributeTableFilterModel::ShowAll ).toInt(); switch ( defaultFilterMode ) { case QgsAttributeTableFilterModel::ShowVisible: filterVisible(); break; case QgsAttributeTableFilterModel::ShowSelected: filterSelected(); break; case QgsAttributeTableFilterModel::ShowAll: default: filterShowAll(); break; } mUpdateExpressionText->registerGetExpressionContextCallback( &_getExpressionContext, mLayer ); mFieldCombo->setFilters( QgsFieldProxyModel::All | QgsFieldProxyModel::HideReadOnly ); mFieldCombo->setLayer( mLayer ); connect( mRunFieldCalc, SIGNAL( clicked() ), this, SLOT( updateFieldFromExpression() ) ); connect( mRunFieldCalcSelected, SIGNAL( clicked() ), this, SLOT( updateFieldFromExpressionSelected() ) ); // NW TODO Fix in 2.6 - Doesn't work with field model for some reason. // connect( mUpdateExpressionText, SIGNAL( returnPressed() ), this, SLOT( updateFieldFromExpression() ) ); connect( mUpdateExpressionText, SIGNAL( fieldChanged( QString, bool ) ), this, SLOT( updateButtonStatus( QString, bool ) ) ); mUpdateExpressionText->setLayer( mLayer ); mUpdateExpressionText->setLeftHandButtonStyle( true ); int initialView = settings.value( "/qgis/attributeTableView", -1 ).toInt(); if ( initialView < 0 ) { initialView = settings.value( "/qgis/attributeTableLastView", QgsDualView::AttributeTable ).toInt(); } mMainView->setView( static_cast< QgsDualView::ViewMode >( initialView ) ); mMainViewButtonGroup->button( initialView )->setChecked( true ); connect( mActionToggleMultiEdit, SIGNAL( toggled( bool ) ), mMainView, SLOT( setMultiEditEnabled( bool ) ) ); connect( mActionSearchForm, SIGNAL( toggled( bool ) ), mMainView, SLOT( toggleSearchMode( bool ) ) ); updateMultiEditButtonState(); if ( mLayer->editFormConfig()->layout() == QgsEditFormConfig::UiFileLayout ) { //not supported with custom UI mActionToggleMultiEdit->setEnabled( false ); mActionToggleMultiEdit->setToolTip( tr( "Multiedit is not supported when using custom UI forms" ) ); mActionSearchForm->setEnabled( false ); mActionSearchForm->setToolTip( tr( "Search is not supported when using custom UI forms" ) ); } editingToggled(); }
QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWidget *parent, Qt::WindowFlags flags ) : QDialog( parent, flags ) , mDock( 0 ) , mLayer( theLayer ) { setupUi( this ); setAttribute( Qt::WA_DeleteOnClose ); QSettings settings; // Initialize the window geometry restoreGeometry( settings.value( "/Windows/BetterAttributeTable/geometry" ).toByteArray() ); QgsDistanceArea myDa; myDa.setSourceCrs( mLayer->crs().srsid() ); myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapRenderer()->hasCrsTransformEnabled() ); myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) ); // Initialize dual view mMainView->init( mLayer, QgisApp::instance()->mapCanvas(), myDa ); // Initialize filter gui elements mFilterActionMapper = new QSignalMapper( this ); mFilterColumnsMenu = new QMenu( this ); mActionFilterColumnsMenu->setMenu( mFilterColumnsMenu ); mApplyFilterButton->setDefaultAction( mActionApplyFilter ); // Set filter icon in a couple of places QIcon filterIcon = QgsApplication::getThemeIcon( "/mActionFilter.svg" ); mActionShowAllFilter->setIcon( filterIcon ); mActionAdvancedFilter->setIcon( filterIcon ); mActionSelectedFilter->setIcon( filterIcon ); mActionVisibleFilter->setIcon( filterIcon ); mActionEditedFilter->setIcon( filterIcon ); // Connect filter signals connect( mActionAdvancedFilter, SIGNAL( triggered() ), SLOT( filterExpressionBuilder() ) ); connect( mActionShowAllFilter, SIGNAL( triggered() ), SLOT( filterShowAll() ) ); connect( mActionSelectedFilter, SIGNAL( triggered() ), SLOT( filterSelected() ) ); connect( mActionVisibleFilter, SIGNAL( triggered() ), SLOT( filterVisible() ) ); connect( mActionEditedFilter, SIGNAL( triggered() ), SLOT( filterEdited() ) ); connect( mFilterActionMapper, SIGNAL( mapped( QObject* ) ), SLOT( filterColumnChanged( QObject* ) ) ); connect( mFilterQuery, SIGNAL( returnPressed() ), SLOT( filterQueryAccepted() ) ); connect( mActionApplyFilter, SIGNAL( triggered() ), SLOT( filterQueryAccepted() ) ); // info from layer to table connect( mLayer, SIGNAL( editingStarted() ), this, SLOT( editingToggled() ) ); connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) ); connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( close() ) ); connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateTitle() ) ); connect( mLayer, SIGNAL( attributeAdded( int ) ), this, SLOT( columnBoxInit() ) ); connect( mLayer, SIGNAL( attributeDeleted( int ) ), this, SLOT( columnBoxInit() ) ); // connect table info to window connect( mMainView, SIGNAL( filterChanged() ), this, SLOT( updateTitle() ) ); // info from table to application connect( this, SIGNAL( saveEdits( QgsMapLayer * ) ), QgisApp::instance(), SLOT( saveEdits( QgsMapLayer * ) ) ); bool myDockFlag = settings.value( "/qgis/dockAttributeTable", false ).toBool(); if ( myDockFlag ) { mDock = new QgsAttributeTableDock( tr( "Attribute table - %1 (%n Feature(s))", "feature count", mMainView->featureCount() ).arg( mLayer->name() ), QgisApp::instance() ); mDock->setAllowedAreas( Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea ); mDock->setWidget( this ); connect( this, SIGNAL( destroyed() ), mDock, SLOT( close() ) ); QgisApp::instance()->addDockWidget( Qt::BottomDockWidgetArea, mDock ); } columnBoxInit(); updateTitle(); mRemoveSelectionButton->setIcon( QgsApplication::getThemeIcon( "/mActionUnselectAttributes.png" ) ); mSelectedToTopButton->setIcon( QgsApplication::getThemeIcon( "/mActionSelectedToTop.png" ) ); mCopySelectedRowsButton->setIcon( QgsApplication::getThemeIcon( "/mActionCopySelected.png" ) ); mZoomMapToSelectedRowsButton->setIcon( QgsApplication::getThemeIcon( "/mActionZoomToSelected.svg" ) ); mPanMapToSelectedRowsButton->setIcon( QgsApplication::getThemeIcon( "/mActionPanToSelected.png" ) ); mInvertSelectionButton->setIcon( QgsApplication::getThemeIcon( "/mActionInvertSelection.png" ) ); mToggleEditingButton->setIcon( QgsApplication::getThemeIcon( "/mActionToggleEditing.svg" ) ); mSaveEditsButton->setIcon( QgsApplication::getThemeIcon( "/mActionSaveEdits.svg" ) ); mDeleteSelectedButton->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteSelected.svg" ) ); mOpenFieldCalculator->setIcon( QgsApplication::getThemeIcon( "/mActionCalculateField.png" ) ); mAddAttribute->setIcon( QgsApplication::getThemeIcon( "/mActionNewAttribute.png" ) ); mRemoveAttribute->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteAttribute.png" ) ); mTableViewButton->setIcon( QgsApplication::getThemeIcon( "/mActionOpenTable.png" ) ); mAttributeViewButton->setIcon( QgsApplication::getThemeIcon( "/mActionPropertyItem.png" ) ); mExpressionSelectButton->setIcon( QgsApplication::getThemeIcon( "/mIconExpressionSelect.svg" ) ); // toggle editing bool canChangeAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues; bool canDeleteFeatures = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteFeatures; bool canAddAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::AddAttributes; bool canDeleteAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteAttributes; bool canAddFeatures = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures; mToggleEditingButton->blockSignals( true ); mToggleEditingButton->setCheckable( true ); mToggleEditingButton->setChecked( mLayer->isEditable() ); mToggleEditingButton->setEnabled( canChangeAttributes && !mLayer->isReadOnly() ); mToggleEditingButton->blockSignals( false ); mSaveEditsButton->setEnabled( canChangeAttributes && mLayer->isEditable() ); mOpenFieldCalculator->setEnabled(( canChangeAttributes || canAddAttributes ) && mLayer->isEditable() ); mDeleteSelectedButton->setEnabled( canDeleteFeatures && mLayer->isEditable() ); mAddAttribute->setEnabled( canAddAttributes && mLayer->isEditable() ); mRemoveAttribute->setEnabled( canDeleteAttributes && mLayer->isEditable() ); mAddFeature->setEnabled( canAddFeatures && mLayer->isEditable() && mLayer->geometryType() == QGis::NoGeometry ); mAddFeature->setHidden( !canAddFeatures || mLayer->geometryType() != QGis::NoGeometry ); mMainViewButtonGroup->setId( mTableViewButton, QgsDualView::AttributeTable ); mMainViewButtonGroup->setId( mAttributeViewButton, QgsDualView::AttributeEditor ); // Load default attribute table filter QgsAttributeTableFilterModel::FilterMode defaultFilterMode = ( QgsAttributeTableFilterModel::FilterMode ) settings.value( "/qgis/attributeTableBehaviour", QgsAttributeTableFilterModel::ShowAll ).toInt(); switch ( defaultFilterMode ) { case QgsAttributeTableFilterModel::ShowVisible: filterVisible(); break; case QgsAttributeTableFilterModel::ShowSelected: filterSelected(); break; case QgsAttributeTableFilterModel::ShowAll: default: filterShowAll(); break; } }
QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttributeTableFilterModel::FilterMode initialMode, QWidget *parent, Qt::WindowFlags flags ) : QDialog( parent, flags ) , mLayer( layer ) { setObjectName( QStringLiteral( "QgsAttributeTableDialog/" ) + layer->id() ); setupUi( this ); connect( mActionCutSelectedRows, &QAction::triggered, this, &QgsAttributeTableDialog::mActionCutSelectedRows_triggered ); connect( mActionCopySelectedRows, &QAction::triggered, this, &QgsAttributeTableDialog::mActionCopySelectedRows_triggered ); connect( mActionPasteFeatures, &QAction::triggered, this, &QgsAttributeTableDialog::mActionPasteFeatures_triggered ); connect( mActionToggleEditing, &QAction::toggled, this, &QgsAttributeTableDialog::mActionToggleEditing_toggled ); connect( mActionSaveEdits, &QAction::triggered, this, &QgsAttributeTableDialog::mActionSaveEdits_triggered ); connect( mActionReload, &QAction::triggered, this, &QgsAttributeTableDialog::mActionReload_triggered ); connect( mActionInvertSelection, &QAction::triggered, this, &QgsAttributeTableDialog::mActionInvertSelection_triggered ); connect( mActionRemoveSelection, &QAction::triggered, this, &QgsAttributeTableDialog::mActionRemoveSelection_triggered ); connect( mActionSelectAll, &QAction::triggered, this, &QgsAttributeTableDialog::mActionSelectAll_triggered ); connect( mActionZoomMapToSelectedRows, &QAction::triggered, this, &QgsAttributeTableDialog::mActionZoomMapToSelectedRows_triggered ); connect( mActionPanMapToSelectedRows, &QAction::triggered, this, &QgsAttributeTableDialog::mActionPanMapToSelectedRows_triggered ); connect( mActionSelectedToTop, &QAction::toggled, this, &QgsAttributeTableDialog::mActionSelectedToTop_toggled ); connect( mActionAddAttribute, &QAction::triggered, this, &QgsAttributeTableDialog::mActionAddAttribute_triggered ); connect( mActionRemoveAttribute, &QAction::triggered, this, &QgsAttributeTableDialog::mActionRemoveAttribute_triggered ); connect( mActionOpenFieldCalculator, &QAction::triggered, this, &QgsAttributeTableDialog::mActionOpenFieldCalculator_triggered ); connect( mActionDeleteSelected, &QAction::triggered, this, &QgsAttributeTableDialog::mActionDeleteSelected_triggered ); connect( mMainView, &QgsDualView::currentChanged, this, &QgsAttributeTableDialog::mMainView_currentChanged ); connect( mActionAddFeature, &QAction::triggered, this, &QgsAttributeTableDialog::mActionAddFeature_triggered ); connect( mActionExpressionSelect, &QAction::triggered, this, &QgsAttributeTableDialog::mActionExpressionSelect_triggered ); connect( mMainView, &QgsDualView::showContextMenuExternally, this, &QgsAttributeTableDialog::showContextMenu ); const QgsFields fields = mLayer->fields(); for ( const QgsField &field : fields ) { mVisibleFields.append( field.name() ); } // Fix selection color on losing focus (Windows) setStyleSheet( QgisApp::instance()->styleSheet() ); setAttribute( Qt::WA_DeleteOnClose ); layout()->setMargin( 0 ); layout()->setContentsMargins( 0, 0, 0, 0 ); static_cast< QGridLayout * >( layout() )->setVerticalSpacing( 0 ); QgsSettings settings; int size = settings.value( QStringLiteral( "/qgis/iconSize" ), 16 ).toInt(); if ( size > 32 ) { size -= 16; } else if ( size == 32 ) { size = 24; } else { size = 16; } mToolbar->setIconSize( QSize( size, size ) ); // Initialize the window geometry restoreGeometry( settings.value( QStringLiteral( "Windows/BetterAttributeTable/geometry" ) ).toByteArray() ); myDa = new QgsDistanceArea(); myDa->setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() ); myDa->setEllipsoid( QgsProject::instance()->ellipsoid() ); mEditorContext.setDistanceArea( *myDa ); mEditorContext.setVectorLayerTools( QgisApp::instance()->vectorLayerTools() ); mEditorContext.setMapCanvas( QgisApp::instance()->mapCanvas() ); QgsFeatureRequest r; bool needsGeom = false; if ( mLayer->geometryType() != QgsWkbTypes::NullGeometry && initialMode == QgsAttributeTableFilterModel::ShowVisible ) { QgsMapCanvas *mc = QgisApp::instance()->mapCanvas(); QgsRectangle extent( mc->mapSettings().mapToLayerCoordinates( layer, mc->extent() ) ); r.setFilterRect( extent ); needsGeom = true; } else if ( initialMode == QgsAttributeTableFilterModel::ShowSelected ) { r.setFilterFids( layer->selectedFeatureIds() ); } if ( !needsGeom ) r.setFlags( QgsFeatureRequest::NoGeometry ); // Initialize dual view mMainView->init( mLayer, QgisApp::instance()->mapCanvas(), r, mEditorContext, false ); QgsAttributeTableConfig config = mLayer->attributeTableConfig(); mMainView->setAttributeTableConfig( config ); // Initialize filter gui elements mFilterActionMapper = new QSignalMapper( this ); mFilterColumnsMenu = new QMenu( this ); mActionFilterColumnsMenu->setMenu( mFilterColumnsMenu ); mApplyFilterButton->setDefaultAction( mActionApplyFilter ); // Set filter icon in a couple of places QIcon filterIcon = QgsApplication::getThemeIcon( "/mActionFilter2.svg" ); mActionShowAllFilter->setIcon( filterIcon ); mActionAdvancedFilter->setIcon( filterIcon ); mActionSelectedFilter->setIcon( filterIcon ); mActionVisibleFilter->setIcon( filterIcon ); mActionEditedFilter->setIcon( filterIcon ); mActionFeatureActions = new QToolButton(); mActionFeatureActions->setAutoRaise( false ); mActionFeatureActions->setPopupMode( QToolButton::InstantPopup ); mActionFeatureActions->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mAction.svg" ) ) ); mActionFeatureActions->setText( tr( "Actions" ) ); mActionFeatureActions->setToolTip( tr( "Actions" ) ); mToolbar->addWidget( mActionFeatureActions ); // Connect filter signals connect( mActionAdvancedFilter, &QAction::triggered, this, &QgsAttributeTableDialog::filterExpressionBuilder ); connect( mActionShowAllFilter, &QAction::triggered, this, &QgsAttributeTableDialog::filterShowAll ); connect( mActionSelectedFilter, &QAction::triggered, this, &QgsAttributeTableDialog::filterSelected ); connect( mActionVisibleFilter, &QAction::triggered, this, &QgsAttributeTableDialog::filterVisible ); connect( mActionEditedFilter, &QAction::triggered, this, &QgsAttributeTableDialog::filterEdited ); connect( mFilterActionMapper, SIGNAL( mapped( QObject * ) ), SLOT( filterColumnChanged( QObject * ) ) ); connect( mFilterQuery, &QLineEdit::returnPressed, this, &QgsAttributeTableDialog::filterQueryAccepted ); connect( mActionApplyFilter, &QAction::triggered, this, &QgsAttributeTableDialog::filterQueryAccepted ); connect( mActionSetStyles, &QAction::triggered, this, &QgsAttributeTableDialog::openConditionalStyles ); // info from layer to table connect( mLayer, &QgsVectorLayer::editingStarted, this, &QgsAttributeTableDialog::editingToggled ); connect( mLayer, &QgsVectorLayer::editingStopped, this, &QgsAttributeTableDialog::editingToggled ); connect( mLayer, &QObject::destroyed, mMainView, &QgsDualView::cancelProgress ); connect( mLayer, &QgsVectorLayer::selectionChanged, this, &QgsAttributeTableDialog::updateTitle ); connect( mLayer, &QgsVectorLayer::featureAdded, this, &QgsAttributeTableDialog::updateTitle ); connect( mLayer, &QgsVectorLayer::featuresDeleted, this, &QgsAttributeTableDialog::updateTitle ); connect( mLayer, &QgsVectorLayer::editingStopped, this, &QgsAttributeTableDialog::updateTitle ); connect( mLayer, &QgsVectorLayer::attributeAdded, this, &QgsAttributeTableDialog::columnBoxInit ); connect( mLayer, &QgsVectorLayer::attributeDeleted, this, &QgsAttributeTableDialog::columnBoxInit ); connect( mLayer, &QgsVectorLayer::readOnlyChanged, this, &QgsAttributeTableDialog::editingToggled ); // connect table info to window connect( mMainView, &QgsDualView::filterChanged, this, &QgsAttributeTableDialog::updateTitle ); connect( mMainView, &QgsDualView::filterExpressionSet, this, &QgsAttributeTableDialog::formFilterSet ); connect( mMainView, &QgsDualView::formModeChanged, this, &QgsAttributeTableDialog::viewModeChanged ); // info from table to application connect( this, &QgsAttributeTableDialog::saveEdits, this, [ = ] { QgisApp::instance()->saveEdits(); } ); const bool dockTable = settings.value( QStringLiteral( "qgis/dockAttributeTable" ), false ).toBool(); if ( dockTable ) { mDock = new QgsAttributeTableDock( QString(), QgisApp::instance() ); mDock->setWidget( this ); connect( this, &QObject::destroyed, mDock, &QWidget::close ); QgisApp::instance()->addDockWidget( Qt::BottomDockWidgetArea, mDock ); } mActionDockUndock->setChecked( dockTable ); connect( mActionDockUndock, &QAction::toggled, this, &QgsAttributeTableDialog::toggleDockMode ); installEventFilter( this ); columnBoxInit(); updateTitle(); mActionRemoveSelection->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeselectAll.svg" ) ) ); mActionSelectAll->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSelectAll.svg" ) ) ); mActionSelectedToTop->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSelectedToTop.svg" ) ) ); mActionCopySelectedRows->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionEditCopy.svg" ) ) ); mActionPasteFeatures->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionEditPaste.svg" ) ) ); mActionZoomMapToSelectedRows->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomToSelected.svg" ) ) ); mActionPanMapToSelectedRows->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionPanToSelected.svg" ) ) ); mActionInvertSelection->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionInvertSelection.svg" ) ) ); mActionToggleEditing->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) ) ); mActionSaveEdits->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSaveEdits.svg" ) ) ); mActionDeleteSelected->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeleteSelected.svg" ) ) ); mActionOpenFieldCalculator->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionCalculateField.svg" ) ) ); mActionAddAttribute->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionNewAttribute.svg" ) ) ); mActionRemoveAttribute->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeleteAttribute.svg" ) ) ); mTableViewButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionOpenTable.svg" ) ) ); mAttributeViewButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFormView.svg" ) ) ); mActionExpressionSelect->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconExpressionSelect.svg" ) ) ); mActionAddFeature->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionNewTableRow.svg" ) ) ); mActionFeatureActions->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mAction.svg" ) ) ); // toggle editing bool canChangeAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues; bool canDeleteFeatures = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteFeatures; bool canAddAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::AddAttributes; bool canDeleteAttributes = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteAttributes; bool canAddFeatures = mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures; mActionToggleEditing->blockSignals( true ); mActionToggleEditing->setCheckable( true ); mActionToggleEditing->setChecked( mLayer->isEditable() ); mActionToggleEditing->blockSignals( false ); mActionSaveEdits->setEnabled( mActionToggleEditing->isEnabled() && mLayer->isEditable() ); mActionReload->setEnabled( ! mLayer->isEditable() ); mActionAddAttribute->setEnabled( ( canChangeAttributes || canAddAttributes ) && mLayer->isEditable() ); mActionRemoveAttribute->setEnabled( canDeleteAttributes && mLayer->isEditable() ); if ( !canDeleteFeatures ) { mToolbar->removeAction( mActionDeleteSelected ); mToolbar->removeAction( mActionCutSelectedRows ); } mActionAddFeature->setEnabled( canAddFeatures && mLayer->isEditable() ); mActionPasteFeatures->setEnabled( canAddFeatures && mLayer->isEditable() ); if ( !canAddFeatures ) { mToolbar->removeAction( mActionAddFeature ); mToolbar->removeAction( mActionPasteFeatures ); } mMainViewButtonGroup->setId( mTableViewButton, QgsDualView::AttributeTable ); mMainViewButtonGroup->setId( mAttributeViewButton, QgsDualView::AttributeEditor ); switch ( initialMode ) { case QgsAttributeTableFilterModel::ShowVisible: filterVisible(); break; case QgsAttributeTableFilterModel::ShowSelected: filterSelected(); break; case QgsAttributeTableFilterModel::ShowAll: default: filterShowAll(); break; } // Layer might have been destroyed while loading! if ( mLayer ) { mUpdateExpressionText->registerExpressionContextGenerator( this ); mFieldCombo->setFilters( QgsFieldProxyModel::AllTypes | QgsFieldProxyModel::HideReadOnly ); mFieldCombo->setLayer( mLayer ); connect( mRunFieldCalc, &QAbstractButton::clicked, this, &QgsAttributeTableDialog::updateFieldFromExpression ); connect( mRunFieldCalcSelected, &QAbstractButton::clicked, this, &QgsAttributeTableDialog::updateFieldFromExpressionSelected ); // NW TODO Fix in 2.6 - Doesn't work with field model for some reason. // connect( mUpdateExpressionText, SIGNAL( returnPressed() ), this, SLOT( updateFieldFromExpression() ) ); connect( mUpdateExpressionText, static_cast < void ( QgsFieldExpressionWidget::* )( const QString &, bool ) > ( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsAttributeTableDialog::updateButtonStatus ); mUpdateExpressionText->setLayer( mLayer ); mUpdateExpressionText->setLeftHandButtonStyle( true ); int initialView = settings.value( QStringLiteral( "qgis/attributeTableView" ), -1 ).toInt(); if ( initialView < 0 ) { initialView = settings.value( QStringLiteral( "qgis/attributeTableLastView" ), QgsDualView::AttributeTable ).toInt(); } mMainView->setView( static_cast< QgsDualView::ViewMode >( initialView ) ); mMainViewButtonGroup->button( initialView )->setChecked( true ); connect( mActionToggleMultiEdit, &QAction::toggled, mMainView, &QgsDualView::setMultiEditEnabled ); connect( mActionSearchForm, &QAction::toggled, mMainView, &QgsDualView::toggleSearchMode ); updateMultiEditButtonState(); if ( mLayer->editFormConfig().layout() == QgsEditFormConfig::UiFileLayout ) { //not supported with custom UI mActionToggleMultiEdit->setEnabled( false ); mActionToggleMultiEdit->setToolTip( tr( "Multiedit is not supported when using custom UI forms" ) ); mActionSearchForm->setEnabled( false ); mActionSearchForm->setToolTip( tr( "Search is not supported when using custom UI forms" ) ); } editingToggled(); // Close and delete if the layer has been destroyed connect( mLayer, &QObject::destroyed, this, &QWidget::close ); } else { QWidget::close(); } }