mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-06 00:07:29 -04:00
[FEATURE] History for attribute table form view display expressions
It's possible to re-use the last 10 display expressions in the form view of the attribute table. The expressions will also be persisted in the project file. Using fields will now show field aliases instead of column names where available.
This commit is contained in:
parent
117261bfb7
commit
63d0a91566
@ -171,13 +171,6 @@ class QgsDualView : QStackedWidget
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
||||
void columnBoxInit();
|
||||
%Docstring
|
||||
Initializes widgets which depend on the attributes of this layer
|
||||
%End
|
||||
|
||||
public slots:
|
||||
|
||||
void setCurrentEditSelection( const QgsFeatureIds &fids );
|
||||
@ -244,6 +237,9 @@ class QgsDualView : QStackedWidget
|
||||
\param mode new mode
|
||||
%End
|
||||
|
||||
protected:
|
||||
virtual void hideEvent( QHideEvent *event );
|
||||
|
||||
};
|
||||
|
||||
class QgsAttributeTableAction : QAction
|
||||
|
@ -56,7 +56,6 @@ QgsDualView::QgsDualView( QWidget *parent )
|
||||
|
||||
mConditionalFormatWidget->hide();
|
||||
|
||||
mPreviewActionMapper = new QSignalMapper( this );
|
||||
|
||||
mPreviewColumnsMenu = new QMenu( this );
|
||||
mActionPreviewColumnsMenu->setMenu( mPreviewColumnsMenu );
|
||||
@ -66,7 +65,6 @@ QgsDualView::QgsDualView( QWidget *parent )
|
||||
|
||||
// Connect layer list preview signals
|
||||
connect( mActionExpressionPreview, &QAction::triggered, this, &QgsDualView::previewExpressionBuilder );
|
||||
connect( mPreviewActionMapper, static_cast < void ( QSignalMapper::* )( QObject * ) > ( &QSignalMapper::mapped ), this, &QgsDualView::previewColumnChanged );
|
||||
connect( mFeatureList, &QgsFeatureListView::displayExpressionChanged, this, &QgsDualView::previewExpressionChanged );
|
||||
}
|
||||
|
||||
@ -149,16 +147,15 @@ void QgsDualView::columnBoxInit()
|
||||
if ( fieldIndex == -1 )
|
||||
continue;
|
||||
|
||||
if ( QgsGui::editorWidgetRegistry()->findBest( mLayer, field.name() ).type() != QLatin1String( "Hidden" ) )
|
||||
QString fieldName = field.name();
|
||||
if ( QgsGui::editorWidgetRegistry()->findBest( mLayer, fieldName ).type() != QLatin1String( "Hidden" ) )
|
||||
{
|
||||
QIcon icon = mLayer->fields().iconForField( fieldIndex );
|
||||
QString text = field.name();
|
||||
QString text = mLayer->attributeDisplayName( fieldIndex );
|
||||
|
||||
// Generate action for the preview popup button of the feature list
|
||||
QAction *previewAction = new QAction( icon, text, mFeatureListPreviewButton );
|
||||
mPreviewActionMapper->setMapping( previewAction, previewAction );
|
||||
connect( previewAction, &QAction::triggered, this, [previewAction, this]( bool ) { this->mPreviewActionMapper->map( previewAction ); }
|
||||
);
|
||||
connect( previewAction, &QAction::triggered, this, [ = ] { previewColumnChanged( previewAction, fieldName ); } );
|
||||
mPreviewColumnsMenu->addAction( previewAction );
|
||||
|
||||
if ( text == defaultField )
|
||||
@ -168,21 +165,26 @@ void QgsDualView::columnBoxInit()
|
||||
}
|
||||
}
|
||||
|
||||
QAction *sortByPreviewExpression = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "sort.svg" ) ), tr( "Sort by preview expression" ), this );
|
||||
connect( sortByPreviewExpression, &QAction::triggered, this, &QgsDualView::sortByPreviewExpression );
|
||||
mFeatureListPreviewButton->addAction( sortByPreviewExpression );
|
||||
|
||||
QAction *separator = new QAction();
|
||||
separator->setSeparator( true );
|
||||
mFeatureListPreviewButton->addAction( separator );
|
||||
restoreRecentDisplayExpressions();
|
||||
|
||||
// If there is no single field found as preview
|
||||
if ( !mFeatureListPreviewButton->defaultAction() )
|
||||
{
|
||||
mFeatureList->setDisplayExpression( displayExpression );
|
||||
mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
|
||||
mDisplayExpression = mFeatureList->displayExpression();
|
||||
setDisplayExpression( mFeatureList->displayExpression() );
|
||||
}
|
||||
else
|
||||
{
|
||||
mFeatureListPreviewButton->defaultAction()->trigger();
|
||||
}
|
||||
|
||||
QAction *sortByPreviewExpression = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "sort.svg" ) ), tr( "Sort by preview expression" ), this );
|
||||
connect( sortByPreviewExpression, &QAction::triggered, this, &QgsDualView::sortByPreviewExpression );
|
||||
mFeatureListPreviewButton->addAction( sortByPreviewExpression );
|
||||
}
|
||||
|
||||
void QgsDualView::setView( QgsDualView::ViewMode view )
|
||||
@ -314,6 +316,95 @@ void QgsDualView::initModels( QgsMapCanvas *mapCanvas, const QgsFeatureRequest &
|
||||
mFeatureListModel = new QgsFeatureListModel( mFilterModel, mFilterModel );
|
||||
}
|
||||
|
||||
void QgsDualView::restoreRecentDisplayExpressions()
|
||||
{
|
||||
const QVariantList previewExpressions = mLayer->customProperty( QStringLiteral( "dualview/previewExpressions" ) ).toList();
|
||||
|
||||
for ( const QVariant &previewExpression : previewExpressions )
|
||||
insertRecentlyUsedDisplayExpression( previewExpression.toString() );
|
||||
}
|
||||
|
||||
void QgsDualView::saveRecentDisplayExpressions() const
|
||||
{
|
||||
QList<QAction *> actions = mFeatureListPreviewButton->actions();
|
||||
|
||||
// Remove existing same action
|
||||
int index = actions.indexOf( mLastDisplayExpressionAction );
|
||||
if ( index != -1 )
|
||||
{
|
||||
QVariantList previewExpressions;
|
||||
for ( ; index < actions.length(); ++index )
|
||||
{
|
||||
QAction *action = actions.at( index );
|
||||
previewExpressions << action->property( "previewExpression" );
|
||||
}
|
||||
|
||||
mLayer->setCustomProperty( QStringLiteral( "dualview/previewExpressions" ), previewExpressions );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsDualView::setDisplayExpression( const QString &expression )
|
||||
{
|
||||
mDisplayExpression = expression;
|
||||
insertRecentlyUsedDisplayExpression( expression );
|
||||
}
|
||||
|
||||
void QgsDualView::insertRecentlyUsedDisplayExpression( const QString &expression )
|
||||
{
|
||||
QList<QAction *> actions = mFeatureListPreviewButton->actions();
|
||||
|
||||
// Remove existing same action
|
||||
int index = actions.indexOf( mLastDisplayExpressionAction );
|
||||
if ( index != -1 )
|
||||
{
|
||||
for ( int i = 0; index + i < actions.length(); ++i )
|
||||
{
|
||||
QAction *action = actions.at( index );
|
||||
if ( action->text() == expression || i >= 9 )
|
||||
{
|
||||
if ( action == mLastDisplayExpressionAction )
|
||||
mLastDisplayExpressionAction = nullptr;
|
||||
mFeatureListPreviewButton->removeAction( action );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !mLastDisplayExpressionAction )
|
||||
mLastDisplayExpressionAction = action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString name = expression;
|
||||
QIcon icon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconExpressionPreview.svg" ) );
|
||||
if ( expression.startsWith( QLatin1String( "COALESCE( \"" ) ) && expression.endsWith( QLatin1String( ", '<NULL>' )" ) ) )
|
||||
{
|
||||
name = expression.mid( 11, expression.length() - 24 ); // Numbers calculated from the COALESCE / <NULL> parts
|
||||
|
||||
int fieldIndex = mLayer->fields().indexOf( name );
|
||||
if ( fieldIndex != -1 )
|
||||
{
|
||||
name = mLayer->attributeDisplayName( fieldIndex );
|
||||
icon = mLayer->fields().iconForField( fieldIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
name = expression;
|
||||
}
|
||||
}
|
||||
|
||||
QAction *previewAction = new QAction( icon, name, mFeatureListPreviewButton );
|
||||
previewAction->setProperty( "previewExpression", expression );
|
||||
connect( previewAction, &QAction::triggered, this, [expression, this]( bool )
|
||||
{
|
||||
setDisplayExpression( expression );
|
||||
mFeatureListPreviewButton->setText( expression );
|
||||
}
|
||||
);
|
||||
|
||||
mFeatureListPreviewButton->insertAction( mLastDisplayExpressionAction, previewAction );
|
||||
mLastDisplayExpressionAction = previewAction;
|
||||
}
|
||||
|
||||
void QgsDualView::on_mFeatureList_aboutToChangeEditSelection( bool &ok )
|
||||
{
|
||||
if ( mLayer->isEditable() && !mAttributeForm->save() )
|
||||
@ -387,33 +478,27 @@ void QgsDualView::previewExpressionBuilder()
|
||||
mFeatureListPreviewButton->setPopupMode( QToolButton::MenuButtonPopup );
|
||||
}
|
||||
|
||||
mDisplayExpression = mFeatureList->displayExpression();
|
||||
setDisplayExpression( mFeatureList->displayExpression() );
|
||||
}
|
||||
|
||||
void QgsDualView::previewColumnChanged( QObject *action )
|
||||
void QgsDualView::previewColumnChanged( QAction *previewAction, const QString &expression )
|
||||
{
|
||||
QAction *previewAction = qobject_cast< QAction * >( action );
|
||||
|
||||
if ( previewAction )
|
||||
if ( !mFeatureList->setDisplayExpression( QStringLiteral( "COALESCE( \"%1\", '<NULL>' )" ).arg( expression ) ) )
|
||||
{
|
||||
if ( !mFeatureList->setDisplayExpression( QStringLiteral( "COALESCE( \"%1\", '<NULL>' )" ).arg( previewAction->text() ) ) )
|
||||
{
|
||||
QMessageBox::warning( this,
|
||||
tr( "Could not set preview column" ),
|
||||
tr( "Could not set column '%1' as preview column.\nParser error:\n%2" )
|
||||
.arg( previewAction->text(), mFeatureList->parserErrorString() )
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
mFeatureListPreviewButton->setDefaultAction( previewAction );
|
||||
mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
|
||||
}
|
||||
QMessageBox::warning( this,
|
||||
tr( "Could not set preview column" ),
|
||||
tr( "Could not set column '%1' as preview column.\nParser error:\n%2" )
|
||||
.arg( previewAction->text(), mFeatureList->parserErrorString() )
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
mFeatureListPreviewButton->setText( previewAction->text() );
|
||||
mFeatureListPreviewButton->setIcon( previewAction->icon() );
|
||||
mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
|
||||
}
|
||||
|
||||
mDisplayExpression = mFeatureList->displayExpression();
|
||||
|
||||
Q_ASSERT( previewAction );
|
||||
setDisplayExpression( mFeatureList->displayExpression() );
|
||||
}
|
||||
|
||||
int QgsDualView::featureCount()
|
||||
@ -438,6 +523,12 @@ void QgsDualView::copyCellContent() const
|
||||
}
|
||||
}
|
||||
|
||||
void QgsDualView::hideEvent( QHideEvent *event )
|
||||
{
|
||||
Q_UNUSED( event )
|
||||
saveRecentDisplayExpressions();
|
||||
}
|
||||
|
||||
void QgsDualView::viewWillShowContextMenu( QMenu *menu, const QModelIndex &atIndex )
|
||||
{
|
||||
if ( !menu )
|
||||
|
@ -197,13 +197,6 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
|
||||
*/
|
||||
QString sortExpression() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Initializes widgets which depend on the attributes of this layer
|
||||
*/
|
||||
void columnBoxInit();
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
@ -265,6 +258,9 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
|
||||
*/
|
||||
void formModeChanged( QgsAttributeForm::Mode mode );
|
||||
|
||||
protected:
|
||||
virtual void hideEvent( QHideEvent *event ) override;
|
||||
|
||||
private slots:
|
||||
|
||||
void on_mFeatureList_aboutToChangeEditSelection( bool &ok );
|
||||
@ -278,7 +274,7 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
|
||||
|
||||
void previewExpressionBuilder();
|
||||
|
||||
void previewColumnChanged( QObject *previewAction );
|
||||
void previewColumnChanged( QAction *previewAction, const QString &expression );
|
||||
|
||||
void viewWillShowContextMenu( QMenu *menu, const QModelIndex &atIndex );
|
||||
|
||||
@ -335,16 +331,26 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
|
||||
void rebuildFullLayerCache();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Initializes widgets which depend on the attributes of this layer
|
||||
*/
|
||||
void columnBoxInit();
|
||||
void initLayerCache( bool cacheGeometry );
|
||||
void initModels( QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request, bool loadFeatures );
|
||||
void restoreRecentDisplayExpressions();
|
||||
void saveRecentDisplayExpressions() const;
|
||||
void setDisplayExpression( const QString &expression );
|
||||
void insertRecentlyUsedDisplayExpression( const QString &expression );
|
||||
|
||||
QgsAttributeEditorContext mEditorContext;
|
||||
QgsAttributeTableModel *mMasterModel = nullptr;
|
||||
QgsAttributeTableFilterModel *mFilterModel = nullptr;
|
||||
QgsFeatureListModel *mFeatureListModel = nullptr;
|
||||
QgsAttributeForm *mAttributeForm = nullptr;
|
||||
QSignalMapper *mPreviewActionMapper = nullptr;
|
||||
QMenu *mPreviewColumnsMenu = nullptr;
|
||||
QMenu *mPreviewActionMenu = nullptr;
|
||||
QAction *mLastDisplayExpressionAction = nullptr;
|
||||
QMenu *mHorizontalHeaderMenu = nullptr;
|
||||
QgsVectorLayerCache *mLayerCache = nullptr;
|
||||
QgsVectorLayer *mLayer = nullptr;
|
||||
|
Loading…
x
Reference in New Issue
Block a user