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(); 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 ) QgsAttributesAvailableWidgetsModel::QgsAttributesAvailableWidgetsModel( QgsVectorLayer *layer, QgsProject *project, QObject *parent )
: QgsAttributesFormModel( layer, project, parent ) : QgsAttributesFormModel( layer, project, parent )
@ -502,6 +513,7 @@ void QgsAttributesAvailableWidgetsModel::populate()
item->setData( ItemFieldConfigRole, cfg ); item->setData( ItemFieldConfigRole, cfg );
item->setData( ItemNameRole, field.name() ); item->setData( ItemNameRole, field.name() );
item->setData( ItemIdRole, field.name() ); // Field names act as ids item->setData( ItemIdRole, field.name() ); // Field names act as ids
item->setData( ItemDisplayRole, field.alias() );
item->setData( ItemTypeRole, QgsAttributesFormData::Field ); item->setData( ItemTypeRole, QgsAttributesFormData::Field );
item->setData( ItemDataRole, itemData ); item->setData( ItemDataRole, itemData );
item->setIcon( fields.iconForField( i, true ) ); item->setIcon( fields.iconForField( i, true ) );
@ -646,6 +658,11 @@ QVariant QgsAttributesAvailableWidgetsModel::data( const QModelIndex &index, int
{ {
case Qt::DisplayRole: case Qt::DisplayRole:
{ {
if ( !showAliases() && item->type() == QgsAttributesFormData::Field )
{
return item->name();
}
return item->displayName().isEmpty() ? item->name() : item->displayName(); return item->displayName().isEmpty() ? item->name() : item->displayName();
} }
@ -682,6 +699,14 @@ QVariant QgsAttributesAvailableWidgetsModel::data( const QModelIndex &index, int
case Qt::ForegroundRole: case Qt::ForegroundRole:
{ {
if ( item->type() == QgsAttributesFormData::Field )
{
if ( showAliases() && item->displayName().isEmpty() )
{
return QBrush( QColor( Qt::lightGray ) );
}
}
if ( item->type() == QgsAttributesFormData::Relation && invalidRelation ) if ( item->type() == QgsAttributesFormData::Relation && invalidRelation )
{ {
return QBrush( QColor( 255, 0, 0 ) ); return QBrush( QColor( 255, 0, 0 ) );
@ -690,11 +715,26 @@ QVariant QgsAttributesAvailableWidgetsModel::data( const QModelIndex &index, int
return QVariant(); 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 ItemDataRole:
case ItemFieldConfigRole: case ItemFieldConfigRole:
case ItemNameRole: case ItemNameRole:
case ItemTypeRole: case ItemTypeRole:
case ItemIdRole: case ItemIdRole:
case ItemDisplayRole:
return item->data( role ); return item->data( role );
default: default:
@ -932,6 +972,7 @@ void QgsAttributesFormLayoutModel::loadAttributeEditorElementItem( QgsAttributeE
editorItem->setData( ItemIdRole, relation.id() ); editorItem->setData( ItemIdRole, relation.id() );
editorItem->setData( ItemNameRole, relation.name() ); editorItem->setData( ItemNameRole, relation.name() );
editorItem->setData( ItemDisplayRole, relationEditorConfig.label );
editorItem->setData( ItemTypeRole, QgsAttributesFormData::Relation ); editorItem->setData( ItemTypeRole, QgsAttributesFormData::Relation );
editorItem->setData( ItemDataRole, itemData ); editorItem->setData( ItemDataRole, itemData );
@ -1055,6 +1096,9 @@ QVariant QgsAttributesFormLayoutModel::data( const QModelIndex &index, int role
if ( !index.isValid() ) if ( !index.isValid() )
return QVariant(); return QVariant();
if ( role == ItemFieldConfigRole ) // This model doesn't store data for that role
return false;
QgsAttributesFormItem *item = itemForIndex( index ); QgsAttributesFormItem *item = itemForIndex( index );
if ( !item ) if ( !item )
return QVariant(); return QVariant();
@ -1077,11 +1121,6 @@ QVariant QgsAttributesFormLayoutModel::data( const QModelIndex &index, int role
{ {
case Qt::DisplayRole: case Qt::DisplayRole:
{ {
if ( !showAliases() && item->type() == QgsAttributesFormData::Field )
{
return item->name();
}
if ( item->type() == QgsAttributesFormData::Relation && invalidRelation ) if ( item->type() == QgsAttributesFormData::Relation && invalidRelation )
{ {
// Invalid relations can have an id, if that's the case, we have a name. // 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(); return item->displayName().isEmpty() ? item->name() : item->displayName();
} }
@ -1146,10 +1190,17 @@ QVariant QgsAttributesFormLayoutModel::data( const QModelIndex &index, int role
} }
} }
if ( item->type() == QgsAttributesFormData::Relation && invalidRelation ) if ( item->type() == QgsAttributesFormData::Relation )
{
if ( invalidRelation )
{ {
return QBrush( QColor( 255, 0, 0 ) ); return QBrush( QColor( 255, 0, 0 ) );
} }
else if ( showAliases() && item->displayName().isEmpty() )
{
return QBrush( QColor( Qt::lightGray ) );
}
}
return QVariant(); return QVariant();
} }
@ -1165,11 +1216,21 @@ QVariant QgsAttributesFormLayoutModel::data( const QModelIndex &index, int role
return font; return font;
} }
} }
if ( item->type() == QgsAttributesFormData::Relation )
{
if ( !invalidRelation && showAliases() && item->displayName().isEmpty() )
{
QFont font = QFont();
font.setItalic( true );
return font;
}
}
return QVariant(); return QVariant();
} }
case ItemDataRole: case ItemDataRole:
case ItemFieldConfigRole:
case ItemNameRole: case ItemNameRole:
case ItemIdRole: case ItemIdRole:
case ItemTypeRole: case ItemTypeRole:
@ -1605,14 +1666,3 @@ void QgsAttributesFormLayoutModel::insertChild( const QModelIndex &parent, int r
itemForIndex( parent )->insertChild( row, std::move( item ) ); itemForIndex( parent )->insertChild( row, std::move( item ) );
endInsertRows(); 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; 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: public slots:
/** /**
* Populates the model with initial data read from the layer. * 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; std::unique_ptr< QgsAttributesFormItem > mRootItem;
QgsVectorLayer *mLayer; QgsVectorLayer *mLayer;
QgsProject *mProject; 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 ); 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: public slots:
void populate() override; void populate() override;
@ -802,8 +804,6 @@ class GUI_EXPORT QgsAttributesFormLayoutModel : public QgsAttributesFormModel
* \param indexes Input list of indexes, potentially with redundant indexes. * \param indexes Input list of indexes, potentially with redundant indexes.
*/ */
QModelIndexList curateIndexesForMimeData( const QModelIndexList &indexes ) const; QModelIndexList curateIndexesForMimeData( const QModelIndexList &indexes ) const;
bool mShowAliases = false;
}; };
Q_DECLARE_METATYPE( QgsAttributesFormData::RelationEditorConfiguration ) Q_DECLARE_METATYPE( QgsAttributesFormData::RelationEditorConfiguration )

View File

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

View File

@ -54,6 +54,23 @@
</property> </property>
</widget> </widget>
</item> </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> <item>
<widget class="QToolButton" name="mTbInitCode"> <widget class="QToolButton" name="mTbInitCode">
<property name="toolTip"> <property name="toolTip">
@ -146,7 +163,7 @@ Use this function to add extra logic to your forms.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="2"> <item row="4" column="2">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -211,23 +228,6 @@ Use this function to add extra logic to your forms.</string>
</property> </property>
</widget> </widget>
</item> </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> </layout>
</widget> </widget>
<widget class="QgsScrollArea" name="scrollArea_2"> <widget class="QgsScrollArea" name="scrollArea_2">
@ -272,6 +272,7 @@ Use this function to add extra logic to your forms.</string>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>mEditorLayoutComboBox</tabstop> <tabstop>mEditorLayoutComboBox</tabstop>
<tabstop>mShowAliasesButton</tabstop>
<tabstop>mTbInitCode</tabstop> <tabstop>mTbInitCode</tabstop>
<tabstop>mFormSuppressCmbBx</tabstop> <tabstop>mFormSuppressCmbBx</tabstop>
<tabstop>mEditFormLineEdit</tabstop> <tabstop>mEditFormLineEdit</tabstop>
@ -279,7 +280,6 @@ Use this function to add extra logic to your forms.</string>
<tabstop>mAddContainerButton</tabstop> <tabstop>mAddContainerButton</tabstop>
<tabstop>mRemoveLayoutItemButton</tabstop> <tabstop>mRemoveLayoutItemButton</tabstop>
<tabstop>mInvertSelectionButton</tabstop> <tabstop>mInvertSelectionButton</tabstop>
<tabstop>mShowAliasesButton</tabstop>
<tabstop>scrollArea_2</tabstop> <tabstop>scrollArea_2</tabstop>
</tabstops> </tabstops>
<resources> <resources>