Merge pull request #9260 from elpaso/form-background-color

Add bg color option to form containers
This commit is contained in:
Alessandro Pasotti 2019-02-25 15:13:36 +01:00 committed by GitHub
commit a615a3b3f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 114 additions and 11 deletions

View File

@ -130,12 +130,13 @@ attribute form if it is set to the drag and drop designer.
%End %End
public: public:
QgsAttributeEditorContainer( const QString &name, QgsAttributeEditorElement *parent ); QgsAttributeEditorContainer( const QString &name, QgsAttributeEditorElement *parent, const QColor &backgroundColor = QColor() );
%Docstring %Docstring
Creates a new attribute editor container Creates a new attribute editor container
:param name: The name to show as title :param name: The name to show as title
:param parent: The parent. May be another container. :param parent: The parent. May be another container.
:param backgroundColor: The optional background color of the container.
%End %End
@ -222,6 +223,20 @@ show or hide this container based on an expression incorporating
the field value controlled by editor widgets. the field value controlled by editor widgets.
.. versionadded:: 3.0 .. versionadded:: 3.0
%End
QColor backgroundColor() const;
%Docstring
backgroundColor
:return: background color of the container
.. versionadded:: 3.8
%End
void setBackgroundColor( const QColor &backgroundColor );
%Docstring
Sets the background color to ``backgroundColor``
%End %End
}; };

View File

@ -134,7 +134,7 @@ Holding Shift modifier key when attempting to toggle collapsed state will expand
.. note:: .. note::
To add Collapsible properties in promoted QtDesigner widgets, you can add the following "Dynamic properties" by clicking on the green + in the propreties palette: To add Collapsible properties in promoted QtDesigner widgets, you can add the following "Dynamic properties" by clicking on the green + in the properties palette:
bool collapsed, bool saveCollapsedState, bool saveCheckedState, QString syncGroup bool collapsed, bool saveCollapsedState, bool saveCheckedState, QString syncGroup
%End %End

View File

@ -21,6 +21,7 @@
#include "qgsfieldcombobox.h" #include "qgsfieldcombobox.h"
#include "qgsqmlwidgetwrapper.h" #include "qgsqmlwidgetwrapper.h"
#include "qgsapplication.h" #include "qgsapplication.h"
#include "qgscolorbutton.h"
QgsAttributesFormProperties::QgsAttributesFormProperties( QgsVectorLayer *layer, QWidget *parent ) QgsAttributesFormProperties::QgsAttributesFormProperties( QgsVectorLayer *layer, QWidget *parent )
: QWidget( parent ) : QWidget( parent )
@ -451,6 +452,7 @@ QTreeWidgetItem *QgsAttributesFormProperties::loadAttributeEditorTreeItem( QgsAt
itemData.setColumnCount( container->columnCount() ); itemData.setColumnCount( container->columnCount() );
itemData.setShowAsGroupBox( container->isGroupBox() ); itemData.setShowAsGroupBox( container->isGroupBox() );
itemData.setBackgroundColor( container->backgroundColor() );
itemData.setVisibilityExpression( container->visibilityExpression() ); itemData.setVisibilityExpression( container->visibilityExpression() );
newWidget = tree->addItem( parent, itemData ); newWidget = tree->addItem( parent, itemData );
@ -582,10 +584,11 @@ QgsAttributeEditorElement *QgsAttributesFormProperties::createAttributeEditorWid
case DnDTreeItemData::Container: case DnDTreeItemData::Container:
{ {
QgsAttributeEditorContainer *container = new QgsAttributeEditorContainer( item->text( 0 ), parent ); QgsAttributeEditorContainer *container = new QgsAttributeEditorContainer( item->text( 0 ), parent, itemData.backgroundColor() );
container->setColumnCount( itemData.columnCount() ); container->setColumnCount( itemData.columnCount() );
container->setIsGroupBox( forceGroup ? true : itemData.showAsGroupBox() ); container->setIsGroupBox( forceGroup ? true : itemData.showAsGroupBox() );
container->setVisibilityExpression( itemData.visibilityExpression() ); container->setVisibilityExpression( itemData.visibilityExpression() );
container->setBackgroundColor( itemData.backgroundColor( ) );
for ( int t = 0; t < item->childCount(); t++ ) for ( int t = 0; t < item->childCount(); t++ )
{ {
@ -1014,6 +1017,7 @@ void DnDTree::onItemDoubleClicked( QTreeWidgetItem *item, int column )
case QgsAttributesFormProperties::DnDTreeItemData::Container: case QgsAttributesFormProperties::DnDTreeItemData::Container:
{ {
QDialog dlg; QDialog dlg;
dlg.setObjectName( QLatin1Literal( "attributeFormPropertiesContainerDialog" ) );
dlg.setWindowTitle( tr( "Configure Container" ) ); dlg.setWindowTitle( tr( "Configure Container" ) );
QFormLayout *layout = new QFormLayout() ; QFormLayout *layout = new QFormLayout() ;
dlg.setLayout( layout ); dlg.setLayout( layout );
@ -1046,6 +1050,17 @@ void DnDTree::onItemDoubleClicked( QTreeWidgetItem *item, int column )
layout->addRow( showAsGroupBox ); layout->addRow( showAsGroupBox );
} }
QgsCollapsibleGroupBox *styleGroupBox = new QgsCollapsibleGroupBox( tr( "Style" ), layout->widget() );
styleGroupBox->setObjectName( QLatin1Literal( "attributeFormPropertiesContainerStyle" ) );
QFormLayout *customizeGroupBoxLayout = new QFormLayout( styleGroupBox ) ;
QgsColorButton *backgroundColorButton = new QgsColorButton( styleGroupBox, tr( "Container Background Color" ) );
backgroundColorButton->setShowNull( true );
backgroundColorButton->setColor( itemData.backgroundColor() );
customizeGroupBoxLayout->addRow( new QLabel( tr( "Background color" ), styleGroupBox ),
backgroundColorButton );
styleGroupBox->setLayout( customizeGroupBoxLayout );
layout->addRow( styleGroupBox );
QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok
| QDialogButtonBox::Cancel ); | QDialogButtonBox::Cancel );
@ -1060,6 +1075,7 @@ void DnDTree::onItemDoubleClicked( QTreeWidgetItem *item, int column )
itemData.setShowAsGroupBox( showAsGroupBox ? showAsGroupBox->isChecked() : true ); itemData.setShowAsGroupBox( showAsGroupBox ? showAsGroupBox->isChecked() : true );
itemData.setName( title->text() ); itemData.setName( title->text() );
itemData.setShowLabel( showLabelCheckbox->isChecked() ); itemData.setShowLabel( showLabelCheckbox->isChecked() );
itemData.setBackgroundColor( backgroundColorButton->color() );
QgsOptionalExpression visibilityExpression; QgsOptionalExpression visibilityExpression;
visibilityExpression.setData( QgsExpression( visibilityExpressionWidget->expression() ) ); visibilityExpression.setData( QgsExpression( visibilityExpressionWidget->expression() ) );
@ -1379,3 +1395,13 @@ void QgsAttributesFormProperties::DnDTreeItemData::setQmlElementEditorConfigurat
mQmlElementEditorConfiguration = qmlElementEditorConfiguration; mQmlElementEditorConfiguration = qmlElementEditorConfiguration;
} }
QColor QgsAttributesFormProperties::DnDTreeItemData::backgroundColor() const
{
return mBackgroundColor;
}
void QgsAttributesFormProperties::DnDTreeItemData::setBackgroundColor( const QColor &backgroundColor )
{
mBackgroundColor = backgroundColor;
}

View File

@ -88,10 +88,11 @@ class APP_EXPORT QgsAttributesFormProperties : public QWidget, private Ui_QgsAtt
//do we need that //do we need that
DnDTreeItemData() = default; DnDTreeItemData() = default;
DnDTreeItemData( Type type, const QString &name, const QString &displayName ) DnDTreeItemData( Type type, const QString &name, const QString &displayName, const QColor &backgroundColor = QColor() )
: mType( type ) : mType( type )
, mName( name ) , mName( name )
, mDisplayName( displayName ) , mDisplayName( displayName )
, mBackgroundColor( backgroundColor )
{} {}
QString name() const { return mName; } QString name() const { return mName; }
@ -123,6 +124,9 @@ class APP_EXPORT QgsAttributesFormProperties : public QWidget, private Ui_QgsAtt
QmlElementEditorConfiguration qmlElementEditorConfiguration() const; QmlElementEditorConfiguration qmlElementEditorConfiguration() const;
void setQmlElementEditorConfiguration( QmlElementEditorConfiguration qmlElementEditorConfiguration ); void setQmlElementEditorConfiguration( QmlElementEditorConfiguration qmlElementEditorConfiguration );
QColor backgroundColor() const;
void setBackgroundColor( const QColor &backgroundColor );
private: private:
Type mType = Field; Type mType = Field;
QString mName; QString mName;
@ -134,6 +138,7 @@ class APP_EXPORT QgsAttributesFormProperties : public QWidget, private Ui_QgsAtt
QgsOptionalExpression mVisibilityExpression; QgsOptionalExpression mVisibilityExpression;
RelationEditorConfiguration mRelationEditorConfiguration; RelationEditorConfiguration mRelationEditorConfiguration;
QmlElementEditorConfiguration mQmlElementEditorConfiguration; QmlElementEditorConfiguration mQmlElementEditorConfiguration;
QColor mBackgroundColor;
}; };

View File

@ -39,6 +39,16 @@ void QgsAttributeEditorContainer::setVisibilityExpression( const QgsOptionalExpr
mVisibilityExpression = visibilityExpression; mVisibilityExpression = visibilityExpression;
} }
QColor QgsAttributeEditorContainer::backgroundColor() const
{
return mBackgroundColor;
}
void QgsAttributeEditorContainer::setBackgroundColor( const QColor &backgroundColor )
{
mBackgroundColor = backgroundColor;
}
QList<QgsAttributeEditorElement *> QgsAttributeEditorContainer::findElements( QgsAttributeEditorElement::AttributeEditorType type ) const QList<QgsAttributeEditorElement *> QgsAttributeEditorContainer::findElements( QgsAttributeEditorElement::AttributeEditorType type ) const
{ {
QList<QgsAttributeEditorElement *> results; QList<QgsAttributeEditorElement *> results;

View File

@ -19,6 +19,7 @@
#include "qgis_core.h" #include "qgis_core.h"
#include "qgsrelation.h" #include "qgsrelation.h"
#include "qgsoptionalexpression.h" #include "qgsoptionalexpression.h"
#include <QColor>
class QgsRelationManager; class QgsRelationManager;
@ -173,11 +174,13 @@ class CORE_EXPORT QgsAttributeEditorContainer : public QgsAttributeEditorElement
* *
* \param name The name to show as title * \param name The name to show as title
* \param parent The parent. May be another container. * \param parent The parent. May be another container.
* \param backgroundColor The optional background color of the container.
*/ */
QgsAttributeEditorContainer( const QString &name, QgsAttributeEditorElement *parent ) QgsAttributeEditorContainer( const QString &name, QgsAttributeEditorElement *parent, const QColor &backgroundColor = QColor() )
: QgsAttributeEditorElement( AeTypeContainer, name, parent ) : QgsAttributeEditorElement( AeTypeContainer, name, parent )
, mIsGroupBox( true ) , mIsGroupBox( true )
, mColumnCount( 1 ) , mColumnCount( 1 )
, mBackgroundColor( backgroundColor )
{} {}
@ -265,6 +268,18 @@ class CORE_EXPORT QgsAttributeEditorContainer : public QgsAttributeEditorElement
*/ */
void setVisibilityExpression( const QgsOptionalExpression &visibilityExpression ); void setVisibilityExpression( const QgsOptionalExpression &visibilityExpression );
/**
* \brief backgroundColor
* \return background color of the container
* \since QGIS 3.8
*/
QColor backgroundColor() const;
/**
* Sets the background color to \a backgroundColor
*/
void setBackgroundColor( const QColor &backgroundColor );
private: private:
void saveConfiguration( QDomElement &elem ) const override; void saveConfiguration( QDomElement &elem ) const override;
QString typeIdentifier() const override; QString typeIdentifier() const override;
@ -273,6 +288,7 @@ class CORE_EXPORT QgsAttributeEditorContainer : public QgsAttributeEditorElement
QList<QgsAttributeEditorElement *> mChildren; QList<QgsAttributeEditorElement *> mChildren;
int mColumnCount; int mColumnCount;
QgsOptionalExpression mVisibilityExpression; QgsOptionalExpression mVisibilityExpression;
QColor mBackgroundColor;
}; };
/** /**

View File

@ -525,7 +525,9 @@ QgsAttributeEditorElement *QgsEditFormConfig::attributeEditorElementFromDomEleme
if ( elem.tagName() == QLatin1String( "attributeEditorContainer" ) ) if ( elem.tagName() == QLatin1String( "attributeEditorContainer" ) )
{ {
QgsAttributeEditorContainer *container = new QgsAttributeEditorContainer( context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:formcontainers" ).arg( layerId ), elem.attribute( QStringLiteral( "name" ) ) ), parent ); QColor backgroundColor( elem.attribute( QStringLiteral( "backgroundColor" ), QString() ) );
QgsAttributeEditorContainer *container = new QgsAttributeEditorContainer( context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:formcontainers" ).arg( layerId ),
elem.attribute( QStringLiteral( "name" ) ) ), parent, backgroundColor );
bool ok; bool ok;
int cc = elem.attribute( QStringLiteral( "columnCount" ) ).toInt( &ok ); int cc = elem.attribute( QStringLiteral( "columnCount" ) ).toInt( &ok );
if ( !ok ) if ( !ok )
@ -625,7 +627,8 @@ void QgsAttributeEditorContainer::saveConfiguration( QDomElement &elem ) const
elem.setAttribute( QStringLiteral( "groupBox" ), mIsGroupBox ? 1 : 0 ); elem.setAttribute( QStringLiteral( "groupBox" ), mIsGroupBox ? 1 : 0 );
elem.setAttribute( QStringLiteral( "visibilityExpressionEnabled" ), mVisibilityExpression.enabled() ? 1 : 0 ); elem.setAttribute( QStringLiteral( "visibilityExpressionEnabled" ), mVisibilityExpression.enabled() ? 1 : 0 );
elem.setAttribute( QStringLiteral( "visibilityExpression" ), mVisibilityExpression->expression() ); elem.setAttribute( QStringLiteral( "visibilityExpression" ), mVisibilityExpression->expression() );
if ( mBackgroundColor.isValid() )
elem.setAttribute( QStringLiteral( "backgroundColor" ), mBackgroundColor.name( ) );
Q_FOREACH ( QgsAttributeEditorElement *child, mChildren ) Q_FOREACH ( QgsAttributeEditorElement *child, mChildren )
{ {
QDomDocument doc = elem.ownerDocument(); QDomDocument doc = elem.ownerDocument();

View File

@ -1707,10 +1707,12 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt
if ( columnCount <= 0 ) if ( columnCount <= 0 )
columnCount = 1; columnCount = 1;
QString widgetName;
QWidget *myContainer = nullptr; QWidget *myContainer = nullptr;
if ( container->isGroupBox() ) if ( container->isGroupBox() )
{ {
QGroupBox *groupBox = new QGroupBox( parent ); QGroupBox *groupBox = new QGroupBox( parent );
widgetName = QStringLiteral( "QGroupBox" );
if ( container->showLabel() ) if ( container->showLabel() )
groupBox->setTitle( container->name() ); groupBox->setTitle( container->name() );
myContainer = groupBox; myContainer = groupBox;
@ -1727,15 +1729,23 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt
scrollArea->setWidget( myContainer ); scrollArea->setWidget( myContainer );
scrollArea->setWidgetResizable( true ); scrollArea->setWidgetResizable( true );
scrollArea->setFrameShape( QFrame::NoFrame ); scrollArea->setFrameShape( QFrame::NoFrame );
widgetName = QStringLiteral( "QScrollArea QWidget" );
newWidgetInfo.widget = scrollArea; newWidgetInfo.widget = scrollArea;
} }
else else
{ {
newWidgetInfo.widget = myContainer; newWidgetInfo.widget = myContainer;
widgetName = QStringLiteral( "QWidget" );
} }
} }
if ( container->backgroundColor().isValid() )
{
QString style {QStringLiteral( "background-color: %1;" ).arg( container->backgroundColor().name() )};
newWidgetInfo.widget->setStyleSheet( style );
}
QGridLayout *gbLayout = new QGridLayout(); QGridLayout *gbLayout = new QGridLayout();
myContainer->setLayout( gbLayout ); myContainer->setLayout( gbLayout );

View File

@ -171,7 +171,7 @@ class GUI_EXPORT QgsCollapsibleGroupBoxBasic : public QGroupBox
* Holding Alt modifier key when toggling collapsed state will synchronize the toggling across other collapsible group boxes with the same syncGroup QString value * Holding Alt modifier key when toggling collapsed state will synchronize the toggling across other collapsible group boxes with the same syncGroup QString value
* Holding Shift modifier key when attempting to toggle collapsed state will expand current group box, then collapse any others with the same syncGroup QString value * Holding Shift modifier key when attempting to toggle collapsed state will expand current group box, then collapse any others with the same syncGroup QString value
* \see basic class QgsCollapsibleGroupBoxBasic which does not auto-save states * \see basic class QgsCollapsibleGroupBoxBasic which does not auto-save states
* \note To add Collapsible properties in promoted QtDesigner widgets, you can add the following "Dynamic properties" by clicking on the green + in the propreties palette: * \note To add Collapsible properties in promoted QtDesigner widgets, you can add the following "Dynamic properties" by clicking on the green + in the properties palette:
* bool collapsed, bool saveCollapsedState, bool saveCheckedState, QString syncGroup * bool collapsed, bool saveCollapsedState, bool saveCheckedState, QString syncGroup
*/ */

View File

@ -20,11 +20,14 @@ from qgis.core import (QgsApplication,
QgsVectorLayer, QgsVectorLayer,
QgsReadWriteContext, QgsReadWriteContext,
QgsEditFormConfig, QgsEditFormConfig,
QgsFetchedContent) QgsFetchedContent,
QgsAttributeEditorContainer,
)
from qgis.gui import QgsGui from qgis.gui import QgsGui
from qgis.testing import start_app, unittest from qgis.testing import start_app, unittest
from qgis.PyQt.QtXml import QDomDocument, QDomElement from qgis.PyQt.QtXml import QDomDocument, QDomElement
from qgis.PyQt.QtGui import QColor
from utilities import unitTestDataPath from utilities import unitTestDataPath
import socketserver import socketserver
import threading import threading
@ -84,14 +87,16 @@ class TestQgsEditFormConfig(unittest.TestCase):
config.setLayout(QgsEditFormConfig.GeneratedLayout) config.setLayout(QgsEditFormConfig.GeneratedLayout)
self.assertEqual(config.layout(), QgsEditFormConfig.GeneratedLayout) self.assertEqual(config.layout(), QgsEditFormConfig.GeneratedLayout)
uiLocal = os.path.join(unitTestDataPath(), '/qgis_local_server/layer_attribute_form.ui') uiLocal = os.path.join(
unitTestDataPath(), '/qgis_local_server/layer_attribute_form.ui')
config.setUiForm(uiLocal) config.setUiForm(uiLocal)
self.assertEqual(config.layout(), QgsEditFormConfig.UiFileLayout) self.assertEqual(config.layout(), QgsEditFormConfig.UiFileLayout)
config.setLayout(QgsEditFormConfig.GeneratedLayout) config.setLayout(QgsEditFormConfig.GeneratedLayout)
self.assertEqual(config.layout(), QgsEditFormConfig.GeneratedLayout) self.assertEqual(config.layout(), QgsEditFormConfig.GeneratedLayout)
uiUrl = 'http://localhost:' + str(self.port) + '/qgis_local_server/layer_attribute_form.ui' uiUrl = 'http://localhost:' + \
str(self.port) + '/qgis_local_server/layer_attribute_form.ui'
config.setUiForm(uiUrl) config.setUiForm(uiUrl)
self.assertEqual(config.layout(), QgsEditFormConfig.UiFileLayout) self.assertEqual(config.layout(), QgsEditFormConfig.UiFileLayout)
content = QgsApplication.networkContentFetcherRegistry().fetch(uiUrl) content = QgsApplication.networkContentFetcherRegistry().fetch(uiUrl)
@ -140,6 +145,19 @@ class TestQgsEditFormConfig(unittest.TestCase):
self.assertFalse(config.labelOnTop(0)) self.assertFalse(config.labelOnTop(0))
self.assertFalse(config.labelOnTop(1)) self.assertFalse(config.labelOnTop(1))
def test_backgroundColorSerialize(self):
"""Test backgroundColor serialization"""
layer = self.createLayer()
config = layer.editFormConfig()
color_name = '#ff00ff'
container = QgsAttributeEditorContainer('container name', None, QColor('#ff00ff'))
doc = QDomDocument()
element = container.toDomElement(doc)
config = QgsEditFormConfig()
container2 = config.attributeEditorElementFromDomElement(element, None, self.layer.id())
self.assertEqual(container2.backgroundColor().name(), color_name)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()