mirror of
https://github.com/qgis/QGIS.git
synced 2025-06-19 00:02:48 -04:00
Merge pull request #8627 from m-kuhn/represent_class_values
Use represention values for classified renderers [FEATURE]
This commit is contained in:
commit
4e38193bf3
@ -279,6 +279,19 @@ Returns the count of symbols matched.
|
||||
.. versionadded:: 3.4
|
||||
%End
|
||||
|
||||
|
||||
static QgsCategoryList createCategories( const QVariantList &values, const QgsSymbol *symbol, QgsVectorLayer *layer = 0, const QString &fieldName = QString() );
|
||||
%Docstring
|
||||
Create categories for a list of ``values``.
|
||||
The returned symbols in the category list will be a modification of ``symbol``.
|
||||
|
||||
If ``layer`` and ``fieldName`` are specified it will try to find nicer values
|
||||
to represent the description for the categories based on the respective field
|
||||
configuration.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "qgslogger.h"
|
||||
#include "qgsproperty.h"
|
||||
#include "qgsstyle.h"
|
||||
#include "qgsfieldformatter.h"
|
||||
#include "qgsfieldformatterregistry.h"
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QDomElement>
|
||||
@ -1032,3 +1034,40 @@ int QgsCategorizedSymbolRenderer::matchToSymbols( QgsStyle *style, const QgsSymb
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
QgsCategoryList QgsCategorizedSymbolRenderer::createCategories( const QList<QVariant> &values, const QgsSymbol *symbol, QgsVectorLayer *layer, const QString &attributeName )
|
||||
{
|
||||
QgsCategoryList cats;
|
||||
QVariantList vals = values;
|
||||
// sort the categories first
|
||||
QgsSymbolLayerUtils::sortVariantList( vals, Qt::AscendingOrder );
|
||||
|
||||
if ( layer && !attributeName.isNull() )
|
||||
{
|
||||
const QgsFields fields = layer->fields();
|
||||
for ( const QVariant &value : vals )
|
||||
{
|
||||
QgsSymbol *newSymbol = symbol->clone();
|
||||
if ( !value.isNull() )
|
||||
{
|
||||
int fieldIdx = fields.lookupField( attributeName );
|
||||
QString categoryName = value.toString();
|
||||
if ( fieldIdx != -1 )
|
||||
{
|
||||
const QgsField field = fields.at( fieldIdx );
|
||||
const QgsEditorWidgetSetup setup = field.editorWidgetSetup();
|
||||
const QgsFieldFormatter *formatter = QgsApplication::fieldFormatterRegistry()->fieldFormatter( setup.type() );
|
||||
categoryName = formatter->representValue( layer, fieldIdx, setup.config(), QVariant(), value );
|
||||
}
|
||||
cats.append( QgsRendererCategory( value, newSymbol, categoryName, true ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add null (default) value
|
||||
QgsSymbol *newSymbol = symbol->clone();
|
||||
cats.append( QgsRendererCategory( QVariant(), newSymbol, QString(), true ) );
|
||||
|
||||
return cats;
|
||||
}
|
||||
|
||||
|
@ -247,6 +247,19 @@ class CORE_EXPORT QgsCategorizedSymbolRenderer : public QgsFeatureRenderer
|
||||
int matchToSymbols( QgsStyle *style, QgsSymbol::SymbolType type,
|
||||
QVariantList &unmatchedCategories SIP_OUT, QStringList &unmatchedSymbols SIP_OUT, bool caseSensitive = true, bool useTolerantMatch = false );
|
||||
|
||||
|
||||
/**
|
||||
* Create categories for a list of \a values.
|
||||
* The returned symbols in the category list will be a modification of \a symbol.
|
||||
*
|
||||
* If \a layer and \a fieldName are specified it will try to find nicer values
|
||||
* to represent the description for the categories based on the respective field
|
||||
* configuration.
|
||||
*
|
||||
* \since QGIS 3.6
|
||||
*/
|
||||
static QgsCategoryList createCategories( const QVariantList &values, const QgsSymbol *symbol, QgsVectorLayer *layer = nullptr, const QString &fieldName = QString() );
|
||||
|
||||
protected:
|
||||
QString mAttrName;
|
||||
QgsCategoryList mCategories;
|
||||
|
@ -635,34 +635,12 @@ void QgsCategorizedSymbolRendererWidget::changeCategorySymbol()
|
||||
}
|
||||
}
|
||||
|
||||
static void _createCategories( QgsCategoryList &cats, QList<QVariant> &values, QgsSymbol *symbol )
|
||||
{
|
||||
// sort the categories first
|
||||
QgsSymbolLayerUtils::sortVariantList( values, Qt::AscendingOrder );
|
||||
|
||||
int num = values.count();
|
||||
|
||||
for ( int i = 0; i < num; i++ )
|
||||
{
|
||||
QVariant value = values[i];
|
||||
QgsSymbol *newSymbol = symbol->clone();
|
||||
if ( ! value.isNull() )
|
||||
{
|
||||
cats.append( QgsRendererCategory( value, newSymbol, value.toString(), true ) );
|
||||
}
|
||||
}
|
||||
|
||||
// add null (default) value
|
||||
QgsSymbol *newSymbol = symbol->clone();
|
||||
cats.append( QgsRendererCategory( QVariant( "" ), newSymbol, QString(), true ) );
|
||||
}
|
||||
|
||||
|
||||
void QgsCategorizedSymbolRendererWidget::addCategories()
|
||||
{
|
||||
QString attrName = mExpressionWidget->currentField();
|
||||
int idx = mLayer->fields().lookupField( attrName );
|
||||
QList<QVariant> unique_vals;
|
||||
QList<QVariant> uniqueValues;
|
||||
if ( idx == -1 )
|
||||
{
|
||||
// Lets assume it's an expression
|
||||
@ -680,21 +658,21 @@ void QgsCategorizedSymbolRendererWidget::addCategories()
|
||||
{
|
||||
context.setFeature( feature );
|
||||
QVariant value = expression->evaluate( &context );
|
||||
if ( unique_vals.contains( value ) )
|
||||
if ( uniqueValues.contains( value ) )
|
||||
continue;
|
||||
unique_vals << value;
|
||||
uniqueValues << value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unique_vals = mLayer->uniqueValues( idx ).toList();
|
||||
uniqueValues = mLayer->uniqueValues( idx ).toList();
|
||||
}
|
||||
|
||||
// ask to abort if too many classes
|
||||
if ( unique_vals.size() >= 1000 )
|
||||
if ( uniqueValues.size() >= 1000 )
|
||||
{
|
||||
int res = QMessageBox::warning( nullptr, tr( "Classify Categories" ),
|
||||
tr( "High number of classes. Classification would yield %1 entries which might not be expected. Continue?" ).arg( unique_vals.size() ),
|
||||
tr( "High number of classes. Classification would yield %1 entries which might not be expected. Continue?" ).arg( uniqueValues.size() ),
|
||||
QMessageBox::Ok | QMessageBox::Cancel,
|
||||
QMessageBox::Cancel );
|
||||
if ( res == QMessageBox::Cancel )
|
||||
@ -709,8 +687,7 @@ void QgsCategorizedSymbolRendererWidget::addCategories()
|
||||
return;
|
||||
#endif
|
||||
|
||||
QgsCategoryList cats;
|
||||
_createCategories( cats, unique_vals, mCategorizedSymbol.get() );
|
||||
QgsCategoryList cats = QgsCategorizedSymbolRenderer::createCategories( uniqueValues, mCategorizedSymbol.get(), mLayer, attrName );
|
||||
bool deleteExisting = false;
|
||||
|
||||
if ( !mOldClassificationAttribute.isEmpty() &&
|
||||
|
@ -25,7 +25,9 @@ from qgis.core import (QgsCategorizedSymbolRenderer,
|
||||
QgsFeature,
|
||||
QgsRenderContext,
|
||||
QgsSymbol,
|
||||
QgsStyle
|
||||
QgsStyle,
|
||||
QgsVectorLayer,
|
||||
QgsEditorWidgetSetup
|
||||
)
|
||||
from qgis.PyQt.QtCore import QVariant
|
||||
from qgis.PyQt.QtGui import QColor
|
||||
@ -483,6 +485,16 @@ class TestQgsCategorizedSymbolRenderer(unittest.TestCase):
|
||||
renderer.setClassAttribute("value - $area")
|
||||
self.assertTrue(renderer.filterNeedsGeometry())
|
||||
|
||||
def testCategories(self):
|
||||
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "addfeat", "memory")
|
||||
layer.setEditorWidgetSetup(1, QgsEditorWidgetSetup("ValueMap", {'map': [{'One': '1'}, {'Two': '2'}]}))
|
||||
|
||||
result = QgsCategorizedSymbolRenderer.createCategories([1, 2, 3], QgsMarkerSymbol(), layer, 'fldint')
|
||||
|
||||
self.assertEqual(result[0].label(), 'One')
|
||||
self.assertEqual(result[1].label(), 'Two')
|
||||
self.assertEqual(result[2].label(), '(3)')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user