Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[feature] Add control over horizontal / vertical stretch for attribute
form widgets

This exposes two new "size" options for edit form widgets, allowing
control over the horizontal and vertical stretch factors for the
widget. By setting a horizontal or vertical stretch, users can
control how edit widgets will relatively resize when resizing
an attribute form.

Eg a user can set a higher horizontal stretch value for widgets which should
"grab" more of the available horizontal space, eg for those widgets
which are expected to have longer values and accordingly will
benefit from the extra space.

Similarly, the vertical stretch setting controls how widgets
will relatively grow vertically when resizing forms vertically. (Note
that only some widgets can vertically grow -- eg. spin boxes
can't be stretched vertically!)

Together these options give more control to users over the exact
layout and sizing of their attribute forms.

By default, the stretch values are set to "Default" which is the
same as previous behavior.
  • Loading branch information
nyalldawson committed May 16, 2023
1 parent 1937917 commit f4554e3
Show file tree
Hide file tree
Showing 10 changed files with 400 additions and 67 deletions.
Expand Up @@ -128,6 +128,50 @@ Controls if this element should be labeled with a title (field, relation or grou
Controls if this element should be labeled with a title (field, relation or groupname).

.. versionadded:: 2.18
%End

int horizontalStretch() const;
%Docstring
Returns the horizontal stretch factor for the element.

.. seealso:: :py:func:`setHorizontalStretch`

.. seealso:: :py:func:`verticalStretch`

.. versionadded:: 3.32
%End

void setHorizontalStretch( int stretch );
%Docstring
Sets the horizontal ``stretch`` factor for the element.

.. seealso:: :py:func:`horizontalStretch`

.. seealso:: :py:func:`setVerticalStretch`

.. versionadded:: 3.32
%End

int verticalStretch() const;
%Docstring
Returns the vertical stretch factor for the element.

.. seealso:: :py:func:`setVerticalStretch`

.. seealso:: :py:func:`horizontalStretch`

.. versionadded:: 3.32
%End

void setVerticalStretch( int stretch );
%Docstring
Sets the vertical ``stretch`` factor for the element.

.. seealso:: :py:func:`verticalStretch`

.. seealso:: :py:func:`setHorizontalStretch`

.. versionadded:: 3.32
%End

LabelStyle labelStyle() const;
Expand Down
5 changes: 5 additions & 0 deletions src/core/editform/qgsattributeeditorelement.cpp
Expand Up @@ -32,6 +32,8 @@ QDomElement QgsAttributeEditorElement::toDomElement( QDomDocument &doc ) const
QDomElement elem = doc.createElement( typeIdentifier() );
elem.setAttribute( QStringLiteral( "name" ), mName );
elem.setAttribute( QStringLiteral( "showLabel" ), mShowLabel );
elem.setAttribute( QStringLiteral( "horizontalStretch" ), mHorizontalStretch );
elem.setAttribute( QStringLiteral( "verticalStretch" ), mVerticalStretch );
elem.appendChild( mLabelStyle.writeXml( doc ) );
saveConfiguration( elem, doc );
return elem;
Expand Down Expand Up @@ -107,6 +109,9 @@ QgsAttributeEditorElement *QgsAttributeEditorElement::create( const QDomElement
else
newElement->setShowLabel( true );

newElement->setHorizontalStretch( element.attribute( QStringLiteral( "horizontalStretch" ), QStringLiteral( "0" ) ).toInt() );
newElement->setVerticalStretch( element.attribute( QStringLiteral( "verticalStretch" ), QStringLiteral( "0" ) ).toInt() );

// Label font and color
LabelStyle style;
style.readXml( element );
Expand Down
47 changes: 44 additions & 3 deletions src/core/editform/qgsattributeeditorelement.h
Expand Up @@ -115,7 +115,6 @@ class CORE_EXPORT QgsAttributeEditorElement SIP_ABSTRACT
: mType( type )
, mName( name )
, mParent( parent )
, mShowLabel( true )
{}

virtual ~QgsAttributeEditorElement() = default;
Expand Down Expand Up @@ -177,6 +176,46 @@ class CORE_EXPORT QgsAttributeEditorElement SIP_ABSTRACT
*/
void setShowLabel( bool showLabel );

/**
* Returns the horizontal stretch factor for the element.
*
* \see setHorizontalStretch()
* \see verticalStretch()
*
* \since QGIS 3.32
*/
int horizontalStretch() const { return mHorizontalStretch; }

/**
* Sets the horizontal \a stretch factor for the element.
*
* \see horizontalStretch()
* \see setVerticalStretch()
*
* \since QGIS 3.32
*/
void setHorizontalStretch( int stretch ) { mHorizontalStretch = stretch; }

/**
* Returns the vertical stretch factor for the element.
*
* \see setVerticalStretch()
* \see horizontalStretch()
*
* \since QGIS 3.32
*/
int verticalStretch() const { return mVerticalStretch; }

/**
* Sets the vertical \a stretch factor for the element.
*
* \see verticalStretch()
* \see setHorizontalStretch()
*
* \since QGIS 3.32
*/
void setVerticalStretch( int stretch ) { mVerticalStretch = stretch; }

/**
* Returns the label style.
* \see setLabelStyle()
Expand All @@ -194,10 +233,12 @@ class CORE_EXPORT QgsAttributeEditorElement SIP_ABSTRACT

protected:
#ifndef SIP_RUN
Qgis::AttributeEditorType mType;
Qgis::AttributeEditorType mType = Qgis::AttributeEditorType::Invalid;
QString mName;
QgsAttributeEditorElement *mParent = nullptr;
bool mShowLabel;
bool mShowLabel = true;
int mHorizontalStretch = 0;
int mVerticalStretch = 0;
LabelStyle mLabelStyle;
#endif

Expand Down
8 changes: 8 additions & 0 deletions src/gui/attributeformconfig/qgsattributeformcontaineredit.cpp
Expand Up @@ -35,6 +35,9 @@ QgsAttributeFormContainerEdit::QgsAttributeFormContainerEdit( QTreeWidgetItem *i
mTypeCombo->addItem( tr( "Group Box" ), QVariant::fromValue( Qgis::AttributeEditorContainerType::GroupBox ) );
mTypeCombo->addItem( tr( "Row" ), QVariant::fromValue( Qgis::AttributeEditorContainerType::Row ) );

mHozStretchSpin->setClearValue( 0, tr( "Default" ) );
mVertStretchSpin->setClearValue( 0, tr( "Default" ) );

mTitleLineEdit->setText( itemData.name() );
mShowLabelCheckBox->setChecked( itemData.showLabel() );
mTypeCombo->setCurrentIndex( mTypeCombo->findData( QVariant::fromValue( itemData.containerType() ) ) );
Expand All @@ -51,6 +54,9 @@ QgsAttributeFormContainerEdit::QgsAttributeFormContainerEdit( QTreeWidgetItem *i
mControlCollapsedGroupBox->setChecked( itemData.collapsedExpression().enabled() );
mCollapsedExpressionWidget->setExpression( itemData.collapsedExpression()->expression() );

mHozStretchSpin->setValue( itemData.horizontalStretch() );
mVertStretchSpin->setValue( itemData.verticalStretch() );

mFormLabelFormatWidget->setLabelStyle( itemData.labelStyle() );

connect( mTypeCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsAttributeFormContainerEdit::containerTypeChanged );
Expand All @@ -73,6 +79,8 @@ void QgsAttributeFormContainerEdit::updateItemData()
itemData.setShowLabel( mShowLabelCheckBox->isChecked() );
itemData.setBackgroundColor( mBackgroundColorButton->color() );
itemData.setLabelStyle( mFormLabelFormatWidget->labelStyle() );
itemData.setHorizontalStretch( mHozStretchSpin->value() );
itemData.setVerticalStretch( mVertStretchSpin->value() );

QgsOptionalExpression visibilityExpression;
visibilityExpression.setData( QgsExpression( mVisibilityExpressionWidget->expression() ) );
Expand Down
6 changes: 6 additions & 0 deletions src/gui/attributeformconfig/qgsattributewidgetedit.cpp
Expand Up @@ -24,13 +24,17 @@ QgsAttributeWidgetEdit::QgsAttributeWidgetEdit( QTreeWidgetItem *item, QWidget *

{
setupUi( this );
mHozStretchSpin->setClearValue( 0, tr( "Default" ) );
mVertStretchSpin->setClearValue( 0, tr( "Default" ) );

const QgsAttributesFormProperties::DnDTreeItemData itemData = mTreeItem->data( 0, QgsAttributesFormProperties::DnDTreeRole ).value<QgsAttributesFormProperties::DnDTreeItemData>();

// common configs
mShowLabelCheckBox->setChecked( itemData.showLabel() );

mFormLabelFormatWidget->setLabelStyle( itemData.labelStyle() );
mHozStretchSpin->setValue( itemData.horizontalStretch() );
mVertStretchSpin->setValue( itemData.verticalStretch() );

switch ( itemData.type() )
{
Expand Down Expand Up @@ -68,6 +72,8 @@ void QgsAttributeWidgetEdit::updateItemData()
// common configs
itemData.setShowLabel( mShowLabelCheckBox->isChecked() );
itemData.setLabelStyle( mFormLabelFormatWidget->labelStyle() );
itemData.setHorizontalStretch( mHozStretchSpin->value() );
itemData.setVerticalStretch( mVertStretchSpin->value() );

// specific configs
switch ( itemData.type() )
Expand Down
78 changes: 78 additions & 0 deletions src/gui/qgsattributeform.cpp
Expand Up @@ -1724,7 +1724,18 @@ void QgsAttributeForm::init()
{
widgetInfo.widget->setFont( widgetInfo.labelStyle.font );
}

layout->addWidget( widgetInfo.widget, row, column, 1, 2 );
if ( widgDef->horizontalStretch() > 0 && widgDef->horizontalStretch() > layout->columnStretch( column + 1 ) )
{
layout->setColumnStretch( column + 1, widgDef->horizontalStretch() );
}
if ( widgDef->verticalStretch() > 0 && widgDef->verticalStretch() > layout->rowStretch( row ) )
{
layout->setRowStretch( row, widgDef->verticalStretch() );
addSpacer = false;
}

if ( containerDef->visibilityExpression().enabled() || containerDef->collapsedExpression().enabled() )
{
registerContainerInformation( new ContainerInformation( widgetInfo.widget, containerDef->visibilityExpression().enabled() ? containerDef->visibilityExpression().data() : QgsExpression(), containerDef->collapsed(), containerDef->collapsedExpression().enabled() ? containerDef->collapsedExpression().data() : QgsExpression() ) );
Expand All @@ -1738,6 +1749,16 @@ void QgsAttributeForm::init()
tabWidget = nullptr;
WidgetInfo widgetInfo = createWidgetFromDef( widgDef, formWidget, mLayer, mContext );
layout->addWidget( widgetInfo.widget, row, column, 1, 2 );
if ( widgDef->verticalStretch() > 0 && widgDef->verticalStretch() > layout->rowStretch( row ) )
{
layout->setRowStretch( row, widgDef->verticalStretch() );
addSpacer = false;
}
if ( widgDef->horizontalStretch() > 0 && widgDef->horizontalStretch() > layout->columnStretch( column + 1 ) )
{
layout->setColumnStretch( column + 1, widgDef->horizontalStretch() );
}

if ( containerDef->visibilityExpression().enabled() || containerDef->collapsedExpression().enabled() )
{
registerContainerInformation( new ContainerInformation( widgetInfo.widget, containerDef->visibilityExpression().enabled() ? containerDef->visibilityExpression().data() : QgsExpression(), containerDef->collapsed(), containerDef->collapsedExpression().enabled() ? containerDef->collapsedExpression().data() : QgsExpression() ) );
Expand Down Expand Up @@ -1802,6 +1823,12 @@ void QgsAttributeForm::init()
QVBoxLayout *c = new QVBoxLayout();
c->addWidget( collapsibleGroupBox );
layout->addLayout( c, row, column, 1, 2 );

if ( widgDef->verticalStretch() > 0 && widgDef->verticalStretch() > layout->rowStretch( row ) )
layout->setRowStretch( row, widgDef->verticalStretch() );
if ( widgDef->horizontalStretch() > 0 && widgDef->horizontalStretch() > layout->columnStretch( column + 1 ) )
layout->setColumnStretch( column + 1, widgDef->horizontalStretch() );

column += 2;

// we consider all relation editors should be expanding
Expand Down Expand Up @@ -1848,6 +1875,17 @@ void QgsAttributeForm::init()
label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
c->addWidget( widgetInfo.widget );
layout->addLayout( c, row, column, 1, 2 );

if ( widgDef->verticalStretch() > 0 && widgDef->verticalStretch() > layout->rowStretch( row ) )
{
layout->setRowStretch( row, widgDef->verticalStretch() );
addSpacer = false;
}
if ( widgDef->horizontalStretch() > 0 && widgDef->horizontalStretch() > layout->columnStretch( column + 1 ) )
{
layout->setColumnStretch( column + 1, widgDef->horizontalStretch() );
}

column += 2;
}
else if ( widgetInfo.labelOnTop )
Expand All @@ -1857,12 +1895,34 @@ void QgsAttributeForm::init()
c->addWidget( label );
c->addWidget( widgetInfo.widget );
layout->addLayout( c, row, column, 1, 2 );

if ( widgDef->verticalStretch() > 0 && widgDef->verticalStretch() > layout->rowStretch( row ) )
{
layout->setRowStretch( row, widgDef->verticalStretch() );
addSpacer = false;
}
if ( widgDef->horizontalStretch() > 0 && widgDef->horizontalStretch() > layout->columnStretch( column + 1 ) )
{
layout->setColumnStretch( column + 1, widgDef->horizontalStretch() );
}

column += 2;
}
else
{
const int widgetColumn = column + 1;
layout->addWidget( label, row, column++ );
layout->addWidget( widgetInfo.widget, row, column++ );

if ( widgDef->verticalStretch() > 0 && widgDef->verticalStretch() > layout->rowStretch( row ) )
{
layout->setRowStretch( row, widgDef->verticalStretch() );
addSpacer = false;
}
if ( widgDef->horizontalStretch() > 0 && widgDef->horizontalStretch() > layout->columnStretch( widgetColumn ) )
{
layout->setColumnStretch( widgetColumn, widgDef->horizontalStretch() );
}
}

// Alias DD overrides
Expand Down Expand Up @@ -2492,9 +2552,13 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt
}
}

// column containing the actual widget, not the label
int widgetColumn = column;

if ( widgetInfo.labelText.isNull() || ! widgetInfo.showLabel )
{
gbLayout->addWidget( widgetInfo.widget, row, column, 1, 2 );
widgetColumn = column + 1;
column += 2;
}
else
Expand Down Expand Up @@ -2552,6 +2616,7 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt

if ( widgetInfo.labelOnTop )
{
widgetColumn = column + 1;
QVBoxLayout *c = new QVBoxLayout();
mypLabel->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
c->layout()->addWidget( mypLabel );
Expand All @@ -2561,11 +2626,24 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt
}
else
{
widgetColumn = column + 1;
gbLayout->addWidget( mypLabel, row, column++ );
gbLayout->addWidget( widgetInfo.widget, row, column++ );
}
}

const int childHorizontalStretch = childDef->horizontalStretch();
const int existingColumnStretch = gbLayout->columnStretch( widgetColumn );
if ( childHorizontalStretch > 0 && childHorizontalStretch > existingColumnStretch )
{
gbLayout->setColumnStretch( widgetColumn, childHorizontalStretch );
}

if ( childDef->verticalStretch() > 0 && childDef->verticalStretch() > gbLayout->rowStretch( row ) )
{
gbLayout->setRowStretch( row, childDef->verticalStretch() );
}

if ( column >= columnCount * 2 )
{
column = 0;
Expand Down

0 comments on commit f4554e3

Please sign in to comment.