Merge row style support for attribute table

Conflicts:
	python/core/qgsconditionalstyle.sip
	python/core/qgsfielduiproperties.sip
	src/core/qgsfielduiproperties.cpp
	src/core/qgsfielduiproperties.h
	src/gui/attributetable/qgsattributetablemodel.cpp
	src/ui/qgsfieldconditionalformatwidget.ui
	tests/src/python/test_qgsconditionalstyle.py
This commit is contained in:
Nathan Woodrow 2015-08-23 12:35:29 +10:00
commit 83115cd16a
14 changed files with 1032 additions and 889 deletions

View File

@ -25,6 +25,12 @@ class QgsConditionalStyle
*/
QPixmap renderPreview();
/**
* @brief Set the name of the style. Names are optional but handy for display
* @param value The name given to the style
*/
void setName( QString value );
/**
* @brief Set the rule for the style. Rules should be of QgsExpression syntax.
* Special value of \@value is replaced at run time with the check value
@ -57,15 +63,27 @@ class QgsConditionalStyle
void setSymbol( QgsSymbolV2* value );
/**
* @brief The icon set for style generated from the set symbol
* @return A QPixmap that was set for the icon using the symbol
* @brief The name of the style.
* @return The name of the style. Names are optional so might be empty.
*/
QgsSymbolV2* symbol() const;
QString displayText() const;
/**
* @brief The name of the style.
* @return The name of the style. Names are optional so might be empty.
*/
QString name() const;
/**
* @brief The symbol used to generate the icon for the style
* @return The QgsSymbolV2 used for the icon
*/
QgsSymbolV2* symbol() const;
/**
* @brief The icon set for style generated from the set symbol
* @return A QPixmap that was set for the icon using the symbol
*/
QPixmap icon() const;
/**
@ -99,6 +117,32 @@ class QgsConditionalStyle
*/
bool isValid() const;
/**
* @brief Find and return the matching styles for the value and feature.
* If no match is found a invalid QgsCondtionalStyle is return.
*
* @return A condtional style that matches the value and feature.
* Check with QgsCondtionalStyle::isValid()
*/
static QList<QgsConditionalStyle> matchingConditionalStyles( QList<QgsConditionalStyle> styles, QVariant value, QgsFeature* feature );
/**
* @brief Find and return the matching style for the value and feature.
* If no match is found a invalid QgsCondtionalStyle is return.
*
* @return A condtional style that matches the value and feature.
* Check with QgsCondtionalStyle::isValid()
*/
static QgsConditionalStyle matchingConditionalStyle( QList<QgsConditionalStyle> styles, QVariant value, QgsFeature* feature );
/**
* @brief Compress a list of styles into a single style. This can be used to stack the elements of the
* styles. The font of the last style is used in the output.
* @param styles The list of styles to compress down
* @return A single style generated from joining each style property.
*/
static QgsConditionalStyle compressStyles( QList<QgsConditionalStyle> styles );
/** Reads vector conditional style specific state from layer Dom node.
*/
virtual bool readXml( const QDomNode& node );

View File

@ -23,28 +23,7 @@ class QgsFieldUIProperties
* @brief Returns the conditional styles set for the field UI properties
* @return A list of conditional styles that have been set.
*/
const QList<QgsConditionalStyle> getConditionalStyles() const;
/**
* @brief Find and return all matching styles for a value and context.
* If no match is found an empty list is returned.
* @param value current cell value
* @param context expression context for evaluating conditional rules
* @return A list of conditional styles that matches the value and context.
* @see matchingConditionalStyle
*/
QList<QgsConditionalStyle> matchingConditionalStyles(QVariant value, QgsExpressionContext& context ) const;
/**
* @brief Find and return the matching style for the value and context.
* If no match is found a invalid QgsConditionalStyle is return.
* @param value current cell value
* @param context expression context for evaluating conditional rules
* @return A conditional style that matches the value and context.
* Check with QgsConditionalStyle::isValid()
* @see matchingConditionalStyles
*/
QgsConditionalStyle matchingConditionalStyle( QVariant value, QgsExpressionContext& context ) const;
const QList<QgsConditionalStyle> conditionalStyles();
/** Reads field ui properties specific state from Dom node.
*/

View File

@ -25,6 +25,7 @@ QgsConditionalStyle::QgsConditionalStyle( const QgsConditionalStyle &other )
, mBackColor( other.mBackColor )
, mTextColor( other.mTextColor )
, mIcon( other.mIcon )
, mName( other.mName )
{
if ( other.mSymbol.data() )
mSymbol.reset( other.mSymbol->clone() );
@ -38,6 +39,7 @@ QgsConditionalStyle& QgsConditionalStyle::operator=( const QgsConditionalStyle &
mBackColor = other.mBackColor;
mTextColor = other.mTextColor;
mIcon = other.mIcon;
mName = other.mName;
if ( other.mSymbol.data() )
{
mSymbol.reset( other.mSymbol->clone() );
@ -53,6 +55,14 @@ QgsConditionalStyle::~QgsConditionalStyle()
{
}
QString QgsConditionalStyle::displayText() const
{
if ( name().isEmpty() )
return rule();
else
return QString( "%1 \n%2" ).arg( name() ).arg( rule() );
}
void QgsConditionalStyle::setSymbol( QgsSymbolV2* value )
{
mValid = true;
@ -103,10 +113,48 @@ QPixmap QgsConditionalStyle::renderPreview()
return pixmap;
}
QList<QgsConditionalStyle> QgsConditionalStyle::matchingConditionalStyles( QList<QgsConditionalStyle> styles, QVariant value, QgsFeature *feature )
{
QList<QgsConditionalStyle> matchingstyles;
foreach ( QgsConditionalStyle style, styles )
{
if ( style.matches( value, feature ) )
matchingstyles.append( style );
}
return matchingstyles;
}
QgsConditionalStyle QgsConditionalStyle::matchingConditionalStyle( QList<QgsConditionalStyle> styles, QVariant value, QgsFeature *feature )
{
foreach ( QgsConditionalStyle style, styles )
{
if ( style.matches( value, feature ) )
return style;
}
return QgsConditionalStyle();
}
QgsConditionalStyle QgsConditionalStyle::compressStyles( QList<QgsConditionalStyle> styles )
{
QgsConditionalStyle style;
foreach ( QgsConditionalStyle s, styles )
{
style.setFont( s.font() );
if ( s.backgroundColor().isValid() && s.backgroundColor().alpha() != 0 )
style.setBackgroundColor( s.backgroundColor() );
if ( s.textColor().isValid() && s.textColor().alpha() != 0 )
style.setTextColor( s.textColor() );
if ( s.symbol() )
style.setSymbol( s.symbol() );
}
return style;
}
bool QgsConditionalStyle::writeXml( QDomNode &node, QDomDocument &doc )
{
QDomElement stylesel = doc.createElement( "style" );
stylesel.setAttribute( "rule", mRule );
stylesel.setAttribute( "name", mName );
stylesel.setAttribute( "background_color", mBackColor.name() );
stylesel.setAttribute( "text_color", mTextColor.name() );
QDomElement labelFontElem = QgsFontUtils::toXmlElement( mFont, doc, "font" );
@ -124,6 +172,7 @@ bool QgsConditionalStyle::readXml( const QDomNode &node )
{
QDomElement styleElm = node.toElement();
setRule( styleElm.attribute( "rule" ) );
setName( styleElm.attribute( "name" ) );
setBackgroundColor( QColor( styleElm.attribute( "background_color" ) ) );
setTextColor( QColor( styleElm.attribute( "text_color" ) ) );
QgsFontUtils::setFromXmlChildNode( mFont, styleElm, "font" );

View File

@ -37,6 +37,12 @@ class CORE_EXPORT QgsConditionalStyle
*/
QPixmap renderPreview();
/**
* @brief Set the name of the style. Names are optional but handy for display
* @param value The name given to the style
*/
void setName( QString value ) { mName = value; mValid = true; }
/**
* @brief Set the rule for the style. Rules should be of QgsExpression syntax.
* Special value of \@value is replaced at run time with the check value
@ -68,6 +74,18 @@ class CORE_EXPORT QgsConditionalStyle
*/
void setSymbol( QgsSymbolV2* value );
/**
* @brief The name of the style.
* @return The name of the style. Names are optional so might be empty.
*/
QString displayText() const;
/**
* @brief The name of the style.
* @return The name of the style. Names are optional so might be empty.
*/
QString name() const { return mName; }
/**
* @brief The icon set for style generated from the set symbol
* @return A QPixmap that was set for the icon using the symbol
@ -111,6 +129,32 @@ class CORE_EXPORT QgsConditionalStyle
*/
bool isValid() const { return mValid; }
/**
* @brief Find and return the matching styles for the value and feature.
* If no match is found a invalid QgsCondtionalStyle is return.
*
* @return A condtional style that matches the value and feature.
* Check with QgsCondtionalStyle::isValid()
*/
static QList<QgsConditionalStyle> matchingConditionalStyles( QList<QgsConditionalStyle> styles, QVariant value, QgsFeature* feature );
/**
* @brief Find and return the matching style for the value and feature.
* If no match is found a invalid QgsCondtionalStyle is return.
*
* @return A condtional style that matches the value and feature.
* Check with QgsCondtionalStyle::isValid()
*/
static QgsConditionalStyle matchingConditionalStyle( QList<QgsConditionalStyle> styles, QVariant value, QgsFeature* feature );
/**
* @brief Compress a list of styles into a single style. This can be used to stack the elements of the
* styles. The font of the last style is used in the output.
* @param styles The list of styles to compress down
* @return A single style generated from joining each style property.
*/
static QgsConditionalStyle compressStyles( QList<QgsConditionalStyle> styles );
/** Reads vector conditional style specific state from layer Dom node.
*/
virtual bool readXml( const QDomNode& node );
@ -119,9 +163,11 @@ class CORE_EXPORT QgsConditionalStyle
*/
virtual bool writeXml( QDomNode & node, QDomDocument & doc );
private:
bool mValid;
QString mName;
QString mRule;
QScopedPointer<QgsSymbolV2> mSymbol;
QFont mFont;

View File

@ -13,32 +13,11 @@ void QgsFieldUIProperties::setConditionalStyles( QList<QgsConditionalStyle> styl
mStyles = styles;
}
QList<QgsConditionalStyle> QgsFieldUIProperties::getConditionalStyles() const
QList<QgsConditionalStyle> QgsFieldUIProperties::conditionalStyles()
{
return mStyles;
}
QList<QgsConditionalStyle> QgsFieldUIProperties::matchingConditionalStyles( QVariant value, QgsExpressionContext& context ) const
{
QList<QgsConditionalStyle> styles;
foreach ( QgsConditionalStyle style, mStyles )
{
if ( style.matches( value, context ) )
styles.append( style );
}
return styles;
}
QgsConditionalStyle QgsFieldUIProperties::matchingConditionalStyle( QVariant value, QgsExpressionContext& context ) const
{
foreach ( QgsConditionalStyle style, mStyles )
{
if ( style.matches( value, context ) )
return style;
}
return QgsConditionalStyle();
}
bool QgsFieldUIProperties::writeXml( QDomNode &node, QDomDocument &doc ) const
{
QDomElement stylesel = doc.createElement( "conditionalstyles" );

View File

@ -30,28 +30,7 @@ class CORE_EXPORT QgsFieldUIProperties
* @brief Returns the conditional styles set for the field UI properties
* @return A list of conditional styles that have been set.
*/
QList<QgsConditionalStyle> getConditionalStyles() const;
/**
* @brief Find and return all matching styles for a value and context.
* If no match is found an empty list is returned.
* @param value current cell value
* @param context expression context for evaluating conditional rules
* @return A list of conditional styles that matches the value and context.
* @see matchingConditionalStyle
*/
QList<QgsConditionalStyle> matchingConditionalStyles( QVariant value, QgsExpressionContext& context ) const;
/**
* @brief Find and return the matching style for the value and context.
* If no match is found a invalid QgsConditionalStyle is return.
* @param value current cell value
* @param context expression context for evaluating conditional rules
* @return A conditional style that matches the value and context.
* Check with QgsConditionalStyle::isValid()
* @see matchingConditionalStyles
*/
QgsConditionalStyle matchingConditionalStyle( QVariant value, QgsExpressionContext& context ) const;
QList<QgsConditionalStyle> conditionalStyles();
/** Reads field ui properties specific state from Dom node.
*/

View File

@ -2044,6 +2044,16 @@ QgsFieldUIProperties QgsVectorLayer::fieldUIProperties( QString fieldName )
return QgsFieldUIProperties();
}
QList<QgsConditionalStyle> QgsVectorLayer::rowStyles()
{
return mRowStyles;
}
void QgsVectorLayer::setRowStyles( QList<QgsConditionalStyle> styles )
{
mRowStyles = styles;
}
void QgsVectorLayer::setFieldUIProperties( QString fieldName, QgsFieldUIProperties props )
{
mFieldProperties.insert( fieldName, props );

View File

@ -27,6 +27,7 @@
#include "qgis.h"
#include "qgsmaplayer.h"
#include "qgsconditionalstyle.h"
#include "qgsfeature.h"
#include "qgsfeatureiterator.h"
#include "qgseditorwidgetconfig.h"
@ -1764,6 +1765,16 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
*/
QgsFieldUIProperties fieldUIProperties( QString fieldName );
QList<QgsConditionalStyle> rowStyles();
/**
* @brief Set the conditional styles that apply to full rows of data in the attribute table.
* Each row will check be checked against each rule.
* @param styles The styles to assign to all the rows
* @note added in QGIS 2.12
*/
void setRowStyles( QList<QgsConditionalStyle> styles );
/**
* @brief Set the the field UI properties for a given field.
* @param fieldName The field name.
@ -2026,6 +2037,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
private: // Private attributes
QHash<QString, QgsFieldUIProperties> mFieldProperties;
QList<QgsConditionalStyle> mRowStyles;
/** Pointer to data provider derived from the abastract base class QgsDataProvider */
QgsVectorDataProvider *mDataProvider;

View File

@ -391,6 +391,13 @@ void QgsAttributeTableModel::loadLayer()
void QgsAttributeTableModel::fieldConditionalStyleChanged( const QString &fieldName )
{
if ( fieldName.isNull() )
{
mRowStylesMap.clear();
emit dataChanged( index( 0, 0 ), index( rowCount() - 1, columnCount() - 1 ) );
return;
}
int fieldIndex = mLayerCache->layer()->fieldNameIndex( fieldName );
if ( fieldIndex == -1 )
return;
@ -588,36 +595,39 @@ QVariant QgsAttributeTableModel::data( const QModelIndex &index, int role ) cons
}
if ( role == Qt::BackgroundColorRole || role == Qt::TextColorRole || role == Qt::DecorationRole || role == Qt::FontRole )
{
mExpressionContext.setFeature( mFeat );
QList<QgsConditionalStyle> styles;
if ( mRowStylesMap.contains( index.row() ) )
{
mExpressionContext.setFeature( mFeat );
styles = mRowStylesMap[index.row()];
}
else
{
styles = QgsConditionalStyle::matchingConditionalStyles( layer()->rowStyles(), QVariant(), &mFeat );
mRowStylesMap.insert( index.row(), styles );
QgsFieldUIProperties props = layer()->fieldUIProperties( field.name() );
QList<QgsConditionalStyle> styles = props.matchingConditionalStyles( val, mExpressionContext );
QgsConditionalStyle style;
foreach ( QgsConditionalStyle s, styles )
{
style.setFont( s.font() );
if ( s.backgroundColor().isValid() && s.backgroundColor().alpha() != 0 )
style.setBackgroundColor( s.backgroundColor() );
if ( s.textColor().isValid() && s.textColor().alpha() != 0 )
style.setTextColor( s.textColor() );
if ( s.symbol() )
style.setSymbol( s.symbol() );
}
if ( style.isValid() )
{
if ( role == Qt::BackgroundColorRole && style.backgroundColor().isValid() )
return style.backgroundColor();
if ( role == Qt::TextColorRole && style.textColor().isValid() )
return style.textColor();
if ( role == Qt::DecorationRole )
return style.icon();
if ( role == Qt::FontRole )
return style.font();
}
}
QgsConditionalStyle rowstyle = QgsConditionalStyle::compressStyles( styles );
QgsFieldUIProperties props = layer()->fieldUIProperties( field.name() );
styles = QgsConditionalStyle::matchingConditionalStyles( props.conditionalStyles(), val, &mFeat );
styles.insert( 0, rowstyle );
QgsConditionalStyle style = QgsConditionalStyle::compressStyles( styles );
if ( style.isValid() )
{
if ( role == Qt::BackgroundColorRole && style.backgroundColor().isValid() )
return style.backgroundColor();
if ( role == Qt::TextColorRole && style.textColor().isValid() )
return style.textColor();
if ( role == Qt::DecorationRole )
return style.icon();
if ( role == Qt::FontRole )
return style.font();
}
}
return val;
}
@ -682,7 +692,6 @@ void QgsAttributeTableModel::reload( const QModelIndex &index1, const QModelInde
}
void QgsAttributeTableModel::executeAction( int action, const QModelIndex &idx ) const
{
QgsFeature f = feature( idx );

View File

@ -299,6 +299,7 @@ class GUI_EXPORT QgsAttributeTableModel: public QAbstractTableModel
QHash<QgsFeatureId, int> mIdRowMap;
QHash<int, QgsFeatureId> mRowIdMap;
mutable QHash<int, QList<QgsConditionalStyle>> mRowStylesMap;
mutable QgsExpressionContext mExpressionContext;

View File

@ -14,20 +14,26 @@ QgsFieldConditionalFormatWidget::QgsFieldConditionalFormatWidget( QWidget *paren
setupUi( this );
mDeleteButton->hide();
connect( mFieldCombo, SIGNAL( fieldChanged( QString ) ), SLOT( fieldChanged( QString ) ) );
connect( fieldRadio, SIGNAL( clicked() ), SLOT( reloadStyles() ) );
connect( rowRadio, SIGNAL( clicked() ), SLOT( reloadStyles() ) );
connect( mNewButton, SIGNAL( clicked() ), SLOT( addNewRule() ) );
connect( mSaveRule, SIGNAL( clicked() ), SLOT( saveRule() ) );
connect( mCancelButton, SIGNAL( clicked() ), SLOT( cancelRule() ) );
connect( mDeleteButton, SIGNAL( clicked() ), SLOT( deleteRule() ) );
connect( listView, SIGNAL( clicked( QModelIndex ) ), SLOT( ruleClicked( QModelIndex ) ) );
connect( mDefaultButtons , SIGNAL( buttonPressed( QAbstractButton* ) ), SLOT( defaultPressed( QAbstractButton* ) ) );
connect( btnChangeIcon , SIGNAL( clicked() ), SLOT( updateIcon() ) );
connect( btnBuildExpression , SIGNAL( clicked() ), SLOT( setExpression() ) );
connect( mPresetsList , SIGNAL( currentIndexChanged( int ) ), SLOT( presetSet( int ) ) );
btnBackgroundColor->setAllowAlpha( true );
btnBackgroundColor->setShowNoColor( true );
btnTextColor->setAllowAlpha( true );
btnTextColor->setShowNoColor( true );
mModel = new QStandardItemModel();
mPresetsModel = new QStandardItemModel();
listView->setModel( mModel );
mPresetsList->setModel( mPresetsModel );
setPresets( defaultPresets() );
}
void QgsFieldConditionalFormatWidget::updateIcon()
@ -63,12 +69,13 @@ void QgsFieldConditionalFormatWidget::setExpression()
}
}
void QgsFieldConditionalFormatWidget::defaultPressed( QAbstractButton *button )
void QgsFieldConditionalFormatWidget::presetSet( int index )
{
QColor backColor = button->property( "backColor" ).value<QColor>();
QColor fontColor = button->property( "fontColor" ).value<QColor>();
btnBackgroundColor->setColor( backColor );
btnTextColor->setColor( fontColor );
if ( index == -1 || mPresets.count() == 0 )
return;
QgsConditionalStyle style = mPresets.at( index );
setFormattingFromStyle( style );
}
void QgsFieldConditionalFormatWidget::setLayer( QgsVectorLayer *theLayer )
@ -80,8 +87,7 @@ void QgsFieldConditionalFormatWidget::setLayer( QgsVectorLayer *theLayer )
void QgsFieldConditionalFormatWidget::ruleClicked( QModelIndex index )
{
QgsFieldUIProperties props = mLayer->fieldUIProperties( mFieldCombo->currentField() );
QList<QgsConditionalStyle> styles = props.getConditionalStyles();
QList<QgsConditionalStyle> styles = getStyles();
QgsConditionalStyle style = styles.at( index.row() );
editStyle( index.row(), style );
}
@ -91,9 +97,18 @@ void QgsFieldConditionalFormatWidget::editStyle( int editIndex, QgsConditionalSt
pages->setCurrentIndex( 1 );
mEditIndex = editIndex;
mEditing = true;
mRuleEdit->setText( style.rule() );
mDeleteButton->show();
loadStyle( style );
}
void QgsFieldConditionalFormatWidget::loadStyle( QgsConditionalStyle style )
{
mRuleEdit->setText( style.rule() );
mNameEdit->setText( style.name() );
setFormattingFromStyle( style );
}
void QgsFieldConditionalFormatWidget::setFormattingFromStyle( QgsConditionalStyle style )
{
btnBackgroundColor->setColor( style.backgroundColor() );
btnTextColor->setColor( style.textColor() );
if ( !style.icon().isNull() )
@ -123,16 +138,41 @@ void QgsFieldConditionalFormatWidget::editStyle( int editIndex, QgsConditionalSt
mFontFamilyCmbBx->setFont( font );
}
QList<QgsConditionalStyle> QgsFieldConditionalFormatWidget::getStyles()
{
QList<QgsConditionalStyle> styles;
if ( fieldRadio->isChecked() )
{
QgsFieldUIProperties props = mLayer->fieldUIProperties( mFieldCombo->currentField() );
styles = props.conditionalStyles();
}
if ( rowRadio->isChecked() )
{
styles = mLayer->rowStyles();
}
return styles;
}
void QgsFieldConditionalFormatWidget::deleteRule()
{
QgsFieldUIProperties props = mLayer->fieldUIProperties( mFieldCombo->currentField() );
QList<QgsConditionalStyle> styles = props.getConditionalStyles();
QList<QgsConditionalStyle> styles = getStyles();
styles.removeAt( mEditIndex );
props.setConditionalStyles( styles );
mLayer->setFieldUIProperties( mFieldCombo->currentField(), props );
QString fieldName;
if ( fieldRadio->isChecked() )
{
QgsFieldUIProperties props = mLayer->fieldUIProperties( mFieldCombo->currentField() );
props.setConditionalStyles( styles );
mLayer->setFieldUIProperties( mFieldCombo->currentField(), props );
fieldName = mFieldCombo->currentField();
}
if ( rowRadio->isChecked() )
{
mLayer->setRowStyles( styles );
}
pages->setCurrentIndex( 0 );
reloadStyles();
emit rulesUpdated( mFieldCombo->currentField() );
emit rulesUpdated( fieldName );
}
void QgsFieldConditionalFormatWidget::cancelRule()
@ -151,11 +191,15 @@ void QgsFieldConditionalFormatWidget::addNewRule()
void QgsFieldConditionalFormatWidget::reset()
{
mSymbol = 0;
mRuleEdit->setText( "@value " );
mNameEdit->clear();
mRuleEdit->clear();
if ( fieldRadio->isChecked() )
{
mRuleEdit->setText( "@value " );
}
btnBackgroundColor->setColor( QColor() );
btnTextColor->setColor( QColor() );
mDefault1->toggle();
defaultPressed( mDefault1 );
mPresetsList->setCurrentIndex( 0 );
mDeleteButton->hide();
mEditing = false;
checkIcon->setChecked( false );
@ -167,13 +211,71 @@ void QgsFieldConditionalFormatWidget::reset()
mFontUnderlineBtn->setChecked( false );
}
void QgsFieldConditionalFormatWidget::setPresets( QList<QgsConditionalStyle> styles )
{
mPresets.clear();
mPresetsModel->clear();
foreach ( QgsConditionalStyle style, styles )
{
if ( style.isValid() )
{
QStandardItem* item = new QStandardItem( "abc - 123" );
if ( style.backgroundColor().isValid() )
item->setBackground( style.backgroundColor() );
if ( style.textColor().isValid() )
item->setForeground( style.textColor() );
if ( style.symbol() )
item->setIcon( style.icon() );
item->setFont( style.font() );
mPresetsModel->appendRow( item );
mPresets.append( style );
}
}
mPresetsList->setCurrentIndex( 0 );
}
QList<QgsConditionalStyle> QgsFieldConditionalFormatWidget::defaultPresets() const
{
QList<QgsConditionalStyle> styles;
QgsConditionalStyle style = QgsConditionalStyle();
style.setBackgroundColor( QColor( 154, 216, 113 ) );
styles.append( style );
style = QgsConditionalStyle();
style.setBackgroundColor( QColor( 251, 193, 78 ) );
styles.append( style );
style = QgsConditionalStyle();
style.setBackgroundColor( QColor( 251, 154, 153 ) );
styles.append( style );
style = QgsConditionalStyle();
style.setTextColor( QColor( 154, 216, 113 ) );
styles.append( style );
style = QgsConditionalStyle();
style.setTextColor( QColor( 251, 193, 78 ) );
styles.append( style );
style = QgsConditionalStyle();
style.setTextColor( QColor( 251, 154, 153 ) );
styles.append( style );
return styles;
}
void QgsFieldConditionalFormatWidget::saveRule()
{
QgsFieldUIProperties props = mLayer->fieldUIProperties( mFieldCombo->currentField() );
QList<QgsConditionalStyle> styles = props.getConditionalStyles();
QList<QgsConditionalStyle> styles;
if ( fieldRadio->isChecked() )
{
QgsFieldUIProperties props = mLayer->fieldUIProperties( mFieldCombo->currentField() );
styles = props.conditionalStyles();
}
if ( rowRadio->isChecked() )
{
styles = mLayer->rowStyles();
}
QgsConditionalStyle style = QgsConditionalStyle();
style.setRule( mRuleEdit->text() );
style.setName( mNameEdit->text() );
QColor backColor = btnBackgroundColor->color();
QColor fontColor = btnTextColor->color();
@ -202,22 +304,32 @@ void QgsFieldConditionalFormatWidget::saveRule()
{
styles.append( style );
}
props.setConditionalStyles( styles );
mLayer->setFieldUIProperties( mFieldCombo->currentField(), props );
QString fieldName;
if ( fieldRadio->isChecked() )
{
QgsFieldUIProperties props = QgsFieldUIProperties();
props.setConditionalStyles( styles );
mLayer->setFieldUIProperties( mFieldCombo->currentField(), props );
fieldName = mFieldCombo->currentField();
}
if ( rowRadio->isChecked() )
{
mLayer->setRowStyles( styles );
}
pages->setCurrentIndex( 0 );
reloadStyles();
emit rulesUpdated( mFieldCombo->currentField() );
emit rulesUpdated( fieldName );
reset();
}
void QgsFieldConditionalFormatWidget::reloadStyles()
{
mModel->clear();
QgsFieldUIProperties props = mLayer->fieldUIProperties( mFieldCombo->currentField() );
QList<QgsConditionalStyle> styles = props.getConditionalStyles();
foreach ( QgsConditionalStyle style, styles )
foreach ( QgsConditionalStyle style, getStyles() )
{
QStandardItem* item = new QStandardItem( style.rule() );
QStandardItem* item = new QStandardItem( style.displayText() );
item->setIcon( QIcon( style.renderPreview() ) );
mModel->appendRow( item );
}

View File

@ -56,10 +56,19 @@ class GUI_EXPORT QgsFieldConditionalFormatWidget : public QWidget, private Ui::Q
*/
void editStyle( int index, QgsConditionalStyle style );
/**
* @param style initial conditional styling options
*/
void loadStyle( QgsConditionalStyle style );
/** Resets the formatting options to their default state.
*/
void reset();
void setPresets( QList<QgsConditionalStyle> styles );
QList<QgsConditionalStyle> defaultPresets() const;
signals:
/** Emitted when the conditional styling rules are updated.
@ -74,12 +83,18 @@ class GUI_EXPORT QgsFieldConditionalFormatWidget : public QWidget, private Ui::Q
int mEditIndex;
bool mEditing;
QStandardItemModel* mModel;
QStandardItemModel* mPresetsModel;
QgsSymbolV2* mSymbol;
QList<QgsConditionalStyle> mPresets;
QList<QgsConditionalStyle> getStyles();
void setFormattingFromStyle( QgsConditionalStyle style );
private slots:
void setExpression();
void updateIcon();
void defaultPressed( QAbstractButton*button );
void presetSet( int index );
bool isCustomSet();
void ruleClicked( QModelIndex index );
void reloadStyles();

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,13 @@ TEST_DATA_DIR = unitTestDataPath()
class TestPyQgsConditionalStyle(TestCase):
def new_feature(self):
feature = QgsFeature()
fields = QgsFields()
fields.append(QgsField("testfield", QVariant.Int))
feature.setFields(fields, True)
feature["testfield"] = 20
return feature
def test_MatchesReturnsTrueForSimpleMatch(self):
style = QgsConditionalStyle("@value > 10")
@ -47,6 +54,21 @@ class TestPyQgsConditionalStyle(TestCase):
context = QgsExpressionContextUtils.createFeatureBasedContext(feature, fields)
assert style.matches(20, context)
def test_MatchingStylesReturnsListOfCorrectStyles(self):
styles = []
style = QgsConditionalStyle("@value > 10")
style.setName("1")
styles.append(style)
style = QgsConditionalStyle("@value > 10")
style.setName("2")
styles.append(style)
style = QgsConditionalStyle("@value < 5")
style.setName("3")
styles.append(style)
out = QgsConditionalStyle.matchingConditionalStyles(styles, 20, self.new_feature())
assert len(out) == 2
out[0].name() == "1"
out[1].name() == "2"
if __name__ == '__main__':
unittest.main()