[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:
Matthias Kuhn 2017-09-05 18:15:11 +02:00
parent 117261bfb7
commit 63d0a91566
No known key found for this signature in database
GPG Key ID: A0E766808764D73F
3 changed files with 142 additions and 49 deletions

View File

@ -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

View File

@ -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 )

View File

@ -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;