mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
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:
commit
83115cd16a
@ -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 );
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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" );
|
||||
|
@ -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;
|
||||
|
@ -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" );
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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 );
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user