Address internal review: Switch to aliases should work for both tree views; move its button to the top row; make sure relations' labels are treated as theire aliases (it makes sense for Form Layout only, because the label setting belongs to the form config, not to the relation itself)

This commit is contained in:
Germán Carrillo 2025-04-17 13:59:35 -05:00
parent c844ba28b0
commit d3c17b716b
5 changed files with 123 additions and 80 deletions

View File

@ -449,6 +449,17 @@ QModelIndex QgsAttributesFormModel::firstRecursiveMatchingModelIndex( const QgsA
return item ? createIndex( item->row(), 0, item ) : QModelIndex();
}
bool QgsAttributesFormModel::showAliases() const
{
return mShowAliases;
}
void QgsAttributesFormModel::setShowAliases( bool show )
{
mShowAliases = show;
emit dataChanged( QModelIndex(), QModelIndex(), QVector<int>() << Qt::DisplayRole << Qt::ForegroundRole << Qt::FontRole );
}
QgsAttributesAvailableWidgetsModel::QgsAttributesAvailableWidgetsModel( QgsVectorLayer *layer, QgsProject *project, QObject *parent )
: QgsAttributesFormModel( layer, project, parent )
@ -502,6 +513,7 @@ void QgsAttributesAvailableWidgetsModel::populate()
item->setData( ItemFieldConfigRole, cfg );
item->setData( ItemNameRole, field.name() );
item->setData( ItemIdRole, field.name() ); // Field names act as ids
item->setData( ItemDisplayRole, field.alias() );
item->setData( ItemTypeRole, QgsAttributesFormData::Field );
item->setData( ItemDataRole, itemData );
item->setIcon( fields.iconForField( i, true ) );
@ -646,6 +658,11 @@ QVariant QgsAttributesAvailableWidgetsModel::data( const QModelIndex &index, int
{
case Qt::DisplayRole:
{
if ( !showAliases() && item->type() == QgsAttributesFormData::Field )
{
return item->name();
}
return item->displayName().isEmpty() ? item->name() : item->displayName();
}
@ -682,6 +699,14 @@ QVariant QgsAttributesAvailableWidgetsModel::data( const QModelIndex &index, int
case Qt::ForegroundRole:
{
if ( item->type() == QgsAttributesFormData::Field )
{
if ( showAliases() && item->displayName().isEmpty() )
{
return QBrush( QColor( Qt::lightGray ) );
}
}
if ( item->type() == QgsAttributesFormData::Relation && invalidRelation )
{
return QBrush( QColor( 255, 0, 0 ) );
@ -690,11 +715,26 @@ QVariant QgsAttributesAvailableWidgetsModel::data( const QModelIndex &index, int
return QVariant();
}
case Qt::FontRole:
{
if ( item->type() == QgsAttributesFormData::Field )
{
if ( showAliases() && item->displayName().isEmpty() )
{
QFont font = QFont();
font.setItalic( true );
return font;
}
}
return QVariant();
}
case ItemDataRole:
case ItemFieldConfigRole:
case ItemNameRole:
case ItemTypeRole:
case ItemIdRole:
case ItemDisplayRole:
return item->data( role );
default:
@ -932,6 +972,7 @@ void QgsAttributesFormLayoutModel::loadAttributeEditorElementItem( QgsAttributeE
editorItem->setData( ItemIdRole, relation.id() );
editorItem->setData( ItemNameRole, relation.name() );
editorItem->setData( ItemDisplayRole, relationEditorConfig.label );
editorItem->setData( ItemTypeRole, QgsAttributesFormData::Relation );
editorItem->setData( ItemDataRole, itemData );
@ -1055,6 +1096,9 @@ QVariant QgsAttributesFormLayoutModel::data( const QModelIndex &index, int role
if ( !index.isValid() )
return QVariant();
if ( role == ItemFieldConfigRole ) // This model doesn't store data for that role
return false;
QgsAttributesFormItem *item = itemForIndex( index );
if ( !item )
return QVariant();
@ -1077,11 +1121,6 @@ QVariant QgsAttributesFormLayoutModel::data( const QModelIndex &index, int role
{
case Qt::DisplayRole:
{
if ( !showAliases() && item->type() == QgsAttributesFormData::Field )
{
return item->name();
}
if ( item->type() == QgsAttributesFormData::Relation && invalidRelation )
{
// Invalid relations can have an id, if that's the case, we have a name.
@ -1092,6 +1131,11 @@ QVariant QgsAttributesFormLayoutModel::data( const QModelIndex &index, int role
}
}
if ( !showAliases() && ( item->type() == QgsAttributesFormData::Field || item->type() == QgsAttributesFormData::Relation ) )
{
return item->name();
}
return item->displayName().isEmpty() ? item->name() : item->displayName();
}
@ -1146,9 +1190,16 @@ QVariant QgsAttributesFormLayoutModel::data( const QModelIndex &index, int role
}
}
if ( item->type() == QgsAttributesFormData::Relation && invalidRelation )
if ( item->type() == QgsAttributesFormData::Relation )
{
return QBrush( QColor( 255, 0, 0 ) );
if ( invalidRelation )
{
return QBrush( QColor( 255, 0, 0 ) );
}
else if ( showAliases() && item->displayName().isEmpty() )
{
return QBrush( QColor( Qt::lightGray ) );
}
}
return QVariant();
@ -1165,11 +1216,21 @@ QVariant QgsAttributesFormLayoutModel::data( const QModelIndex &index, int role
return font;
}
}
if ( item->type() == QgsAttributesFormData::Relation )
{
if ( !invalidRelation && showAliases() && item->displayName().isEmpty() )
{
QFont font = QFont();
font.setItalic( true );
return font;
}
}
return QVariant();
}
case ItemDataRole:
case ItemFieldConfigRole:
case ItemNameRole:
case ItemIdRole:
case ItemTypeRole:
@ -1605,14 +1666,3 @@ void QgsAttributesFormLayoutModel::insertChild( const QModelIndex &parent, int r
itemForIndex( parent )->insertChild( row, std::move( item ) );
endInsertRows();
}
bool QgsAttributesFormLayoutModel::showAliases() const
{
return mShowAliases;
}
void QgsAttributesFormLayoutModel::setShowAliases( bool show )
{
mShowAliases = show;
emit dataChanged( QModelIndex(), QModelIndex(), QVector<int>() << Qt::DisplayRole << Qt::ForegroundRole << Qt::FontRole );
}

View File

@ -578,6 +578,20 @@ class GUI_EXPORT QgsAttributesFormModel : public QAbstractItemModel
*/
QModelIndex firstRecursiveMatchingModelIndex( const QgsAttributesFormData::AttributesFormItemType &itemType, const QString &itemId ) const;
/**
* Returns whether field aliases are preferred over field names as item text.
*
* \see setShowAliases()
*/
bool showAliases() const;
/**
* Sets whether field aliases should be preferred over field names as item text.
*
* \see showAliases()
*/
void setShowAliases( bool show );
public slots:
/**
* Populates the model with initial data read from the layer.
@ -615,6 +629,8 @@ class GUI_EXPORT QgsAttributesFormModel : public QAbstractItemModel
std::unique_ptr< QgsAttributesFormItem > mRootItem;
QgsVectorLayer *mLayer;
QgsProject *mProject;
bool mShowAliases = false;
};
@ -765,20 +781,6 @@ class GUI_EXPORT QgsAttributesFormLayoutModel : public QgsAttributesFormModel
*/
void insertChild( const QModelIndex &parent, int row, const QString &itemId, QgsAttributesFormData::AttributesFormItemType itemType, const QString &itemName );
/**
* Returns whether field aliases are preferred over field names as item text.
*
* \see setShowAliases()
*/
bool showAliases() const;
/**
* Sets whether field aliases should be preferred over field names as item text.
*
* \see showAliases()
*/
void setShowAliases( bool show );
public slots:
void populate() override;
@ -802,8 +804,6 @@ class GUI_EXPORT QgsAttributesFormLayoutModel : public QgsAttributesFormModel
* \param indexes Input list of indexes, potentially with redundant indexes.
*/
QModelIndexList curateIndexesForMimeData( const QModelIndexList &indexes ) const;
bool mShowAliases = false;
};
Q_DECLARE_METATYPE( QgsAttributesFormData::RelationEditorConfiguration )

View File

@ -38,7 +38,7 @@
#include "qgshelp.h"
#include "qgsxmlutils.h"
const QgsSettingsEntryBool *QgsAttributesFormProperties::settingShowAliases = new QgsSettingsEntryBool( QStringLiteral( "show-aliases" ), sTreeAttributesForm, false, QStringLiteral( "Whether to show aliases (true) or names (false) in the Form Layout panel." ) );
const QgsSettingsEntryBool *QgsAttributesFormProperties::settingShowAliases = new QgsSettingsEntryBool( QStringLiteral( "show-aliases" ), sTreeAttributesForm, false, QStringLiteral( "Whether to show aliases (true) or names (false) in both the Available Widgets and the Form Layout panels." ) );
QgsAttributesFormProperties::QgsAttributesFormProperties( QgsVectorLayer *layer, QWidget *parent )
: QWidget( parent )
@ -129,6 +129,7 @@ void QgsAttributesFormProperties::initAvailableWidgetsView()
mAvailableWidgetsView->setDragDropMode( QAbstractItemView::DragDropMode::DragOnly );
mAvailableWidgetsModel->populate();
mAvailableWidgetsModel->setShowAliases( settingShowAliases->value() );
mAvailableWidgetsView->expandAll();
}
@ -342,7 +343,10 @@ void QgsAttributesFormProperties::storeAttributeTypeDialog()
QModelIndex index = mAvailableWidgetsModel->fieldModelIndex( fieldName );
if ( index.isValid() )
{
mAvailableWidgetsModel->setData( index, QVariant::fromValue<QgsAttributesFormData::FieldConfig>( cfg ), QgsAttributesFormModel::ItemFieldConfigRole );
mAvailableWidgetsModel->setData( index, mAttributeTypeDialog->alias(), QgsAttributesFormModel::ItemDisplayRole );
}
// Save alias to each matching field item in Form Layout model
mFormLayoutModel->updateAliasForFieldItems( fieldName, mAttributeTypeDialog->alias() );
@ -375,6 +379,7 @@ void QgsAttributesFormProperties::storeAttributeWidgetEdit( const QModelIndex &i
{
QgsAttributesFormData::RelationEditorConfiguration config = mAttributeWidgetEdit->updatedRelationConfiguration();
itemData.setRelationEditorConfiguration( config );
mFormLayoutModel->setData( index, config.label, QgsAttributesFormLayoutModel::ItemDisplayRole );
}
mFormLayoutModel->setData( index, itemData, QgsAttributesFormLayoutModel::ItemDataRole );
}
@ -447,17 +452,16 @@ void QgsAttributesFormProperties::loadAttributeContainerEdit()
mAttributeTypeFrame->layout()->addWidget( mAttributeContainerEdit );
}
void QgsAttributesFormProperties::onAttributeSelectionChanged( const QItemSelection &, const QItemSelection &deselected )
void QgsAttributesFormProperties::onAttributeSelectionChanged( const QItemSelection &, const QItemSelection & )
{
disconnect( mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
QModelIndex index = previousIndex( mAvailableWidgetsView, deselected );
// Get corresponding index in Form Layout
if ( index.isValid() )
QModelIndex index;
if ( mFormLayoutView->selectionModel()->selectedRows( 0 ).count() == 1 )
{
const auto itemType = static_cast< QgsAttributesFormData::AttributesFormItemType >( index.data( QgsAttributesFormLayoutModel::ItemTypeRole ).toInt() );
const QString itemId = index.data( QgsAttributesFormLayoutModel::ItemIdRole ).toString();
index = mFormLayoutModel->firstRecursiveMatchingModelIndex( itemType, itemId );
// Go to the form layout view and store the single-selected index, as
// it will be used to store its current settings before being deselected
index = mFormLayoutView->selectionModel()->selectedIndexes().at( 0 );
}
loadAttributeSpecificEditor( mAvailableWidgetsView, mFormLayoutView, index );
@ -468,24 +472,19 @@ void QgsAttributesFormProperties::onFormLayoutSelectionChanged( const QItemSelec
{
// when the selection changes in the DnD layout, sync the main tree
disconnect( mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
QModelIndex index = previousIndex( mFormLayoutView, deselected );
loadAttributeSpecificEditor( mFormLayoutView, mAvailableWidgetsView, index );
connect( mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
}
QModelIndex QgsAttributesFormProperties::previousIndex( const QgsAttributesFormBaseView *view, const QItemSelection &deselected ) const
{
QModelIndex index;
if ( deselected.indexes().count() == 1 )
{
index = deselected.indexes().at( 0 );
}
else if ( deselected.indexes().count() == 0 && view->selectionModel()->selectedIndexes().count() == 2 )
else if ( deselected.indexes().count() == 0 && mFormLayoutView->selectionModel()->selectedIndexes().count() == 2 )
{
// There was 1 selected, it was not deselected, but instead a new item was added to selection
index = view->selectionModel()->selectedIndexes().at( 0 );
index = mFormLayoutView->selectionModel()->selectedIndexes().at( 0 );
}
return index;
loadAttributeSpecificEditor( mFormLayoutView, mAvailableWidgetsView, index );
connect( mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
}
void QgsAttributesFormProperties::loadAttributeSpecificEditor( QgsAttributesFormBaseView *emitter, QgsAttributesFormBaseView *receiver, QModelIndex &deselectedFormLayoutIndex )
@ -616,6 +615,7 @@ void QgsAttributesFormProperties::onInvertSelectionButtonClicked( bool checked )
void QgsAttributesFormProperties::toggleShowAliases( bool checked )
{
settingShowAliases->setValue( checked );
mAvailableWidgetsModel->setShowAliases( checked );
mFormLayoutModel->setShowAliases( checked );
}
@ -678,7 +678,6 @@ void QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged( int
mAddContainerButton->setVisible( false );
mRemoveLayoutItemButton->setVisible( false );
mInvertSelectionButton->setVisible( false );
mShowAliasesButton->setVisible( false );
break;
case Qgis::AttributeFormLayout::DragAndDrop:
@ -687,7 +686,6 @@ void QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged( int
mAddContainerButton->setVisible( true );
mRemoveLayoutItemButton->setVisible( true );
mInvertSelectionButton->setVisible( true );
mShowAliasesButton->setVisible( true );
break;
case Qgis::AttributeFormLayout::UiFile:
@ -697,7 +695,6 @@ void QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged( int
mAddContainerButton->setVisible( false );
mRemoveLayoutItemButton->setVisible( false );
mInvertSelectionButton->setVisible( false );
mShowAliasesButton->setVisible( false );
break;
}
@ -1541,6 +1538,7 @@ void QgsAttributesFormProperties::updatedFields()
if ( fieldConfigs.contains( fieldName ) )
{
mAvailableWidgetsModel->setData( index, fieldConfigs[fieldName], QgsAttributesFormModel::ItemFieldConfigRole );
mAvailableWidgetsModel->setData( index, fieldConfigs[fieldName].mAlias, QgsAttributesFormModel::ItemDisplayRole );
}
}
}

View File

@ -140,11 +140,6 @@ class GUI_EXPORT QgsAttributesFormProperties : public QWidget, public QgsExpress
void updatedFields();
private:
/**
* Gets the index that was previously selected to store configuration when changing item selection.
*/
QModelIndex previousIndex( const QgsAttributesFormBaseView *view, const QItemSelection &deselected ) const;
//! this will clean the right panel
void clearAttributeTypeFrame();

View File

@ -54,6 +54,23 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mShowAliasesButton">
<property name="toolTip">
<string>Show field aliases instead of names</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mIconFonts.svg</normaloff>:/images/themes/default/mIconFonts.svg</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mTbInitCode">
<property name="toolTip">
@ -146,7 +163,7 @@ Use this function to add extra logic to your forms.</string>
</property>
</widget>
</item>
<item row="5" column="2">
<item row="4" column="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -211,23 +228,6 @@ Use this function to add extra logic to your forms.</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QToolButton" name="mShowAliasesButton">
<property name="toolTip">
<string>Show field aliases instead of names</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mIconFonts.svg</normaloff>:/images/themes/default/mIconFonts.svg</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QgsScrollArea" name="scrollArea_2">
@ -272,6 +272,7 @@ Use this function to add extra logic to your forms.</string>
</customwidgets>
<tabstops>
<tabstop>mEditorLayoutComboBox</tabstop>
<tabstop>mShowAliasesButton</tabstop>
<tabstop>mTbInitCode</tabstop>
<tabstop>mFormSuppressCmbBx</tabstop>
<tabstop>mEditFormLineEdit</tabstop>
@ -279,7 +280,6 @@ Use this function to add extra logic to your forms.</string>
<tabstop>mAddContainerButton</tabstop>
<tabstop>mRemoveLayoutItemButton</tabstop>
<tabstop>mInvertSelectionButton</tabstop>
<tabstop>mShowAliasesButton</tabstop>
<tabstop>scrollArea_2</tabstop>
</tabstops>
<resources>