Skip to content

Commit

Permalink
Merge row style support for attribute table
Browse files Browse the repository at this point in the history
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
  • Loading branch information
NathanW2 committed Aug 23, 2015
2 parents b39055b + b87073e commit 83115cd
Show file tree
Hide file tree
Showing 14 changed files with 1,030 additions and 887 deletions.
50 changes: 47 additions & 3 deletions python/core/qgsconditionalstyle.sip
Expand Up @@ -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
Expand Down Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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 );
Expand Down
23 changes: 1 addition & 22 deletions python/core/qgsfielduiproperties.sip
Expand Up @@ -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.
*/
Expand Down
49 changes: 49 additions & 0 deletions src/core/qgsconditionalstyle.cpp
Expand Up @@ -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() );
Expand All @@ -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() );
Expand All @@ -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;
Expand Down Expand Up @@ -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" );
Expand All @@ -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" );
Expand Down
46 changes: 46 additions & 0 deletions src/core/qgsconditionalstyle.h
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 );
Expand All @@ -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;
Expand Down
23 changes: 1 addition & 22 deletions src/core/qgsfielduiproperties.cpp
Expand Up @@ -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" );
Expand Down
23 changes: 1 addition & 22 deletions src/core/qgsfielduiproperties.h
Expand Up @@ -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.
*/
Expand Down
10 changes: 10 additions & 0 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -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 );
Expand Down
12 changes: 12 additions & 0 deletions src/core/qgsvectorlayer.h
Expand Up @@ -27,6 +27,7 @@

#include "qgis.h"
#include "qgsmaplayer.h"
#include "qgsconditionalstyle.h"
#include "qgsfeature.h"
#include "qgsfeatureiterator.h"
#include "qgseditorwidgetconfig.h"
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 83115cd

Please sign in to comment.