Merge pull request #31963 from 3nids/fix_bool_attrtable

fix false boolean not shown as so in attribute table
This commit is contained in:
Denis Rouzaud 2019-09-24 14:31:45 +02:00 committed by GitHub
commit f21e03c5ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 231 additions and 8 deletions

View File

@ -0,0 +1,43 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/fieldformatter/qgscheckboxfieldformatter.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsCheckBoxFieldFormatter : QgsFieldFormatter
{
%Docstring
Field formatter for a checkbox field.
.. versionadded:: 3.10
%End
%TypeHeaderCode
#include "qgscheckboxfieldformatter.h"
%End
public:
QgsCheckBoxFieldFormatter();
%Docstring
Constructor for QgsCheckBoxFieldFormatter.
%End
virtual QString id() const;
virtual QString representValue( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value ) const;
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/fieldformatter/qgscheckboxfieldformatter.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -29,7 +29,11 @@ This is an abstract base class and will always need to be subclassed.
#include "qgsfieldformatter.h"
%End
public:
QgsFieldFormatter();
%Docstring
Default constructor
%End
virtual ~QgsFieldFormatter();

View File

@ -321,6 +321,7 @@
%Include auto_generated/geometry/qgswkbptr.sip
%Include auto_generated/./3d/qgs3drendererregistry.sip
%Include auto_generated/./3d/qgsabstract3drenderer.sip
%Include auto_generated/fieldformatter/qgscheckboxfieldformatter.sip
%Include auto_generated/fieldformatter/qgsrangefieldformatter.sip
%Include auto_generated/fieldformatter/qgsdatetimefieldformatter.sip
%Include auto_generated/fieldformatter/qgsfallbackfieldformatter.sip

View File

@ -7,7 +7,7 @@
--indent-labels
--indent-namespaces
--indent-switches
--max-instatement-indent=40
--max-instatement-indent=80
--min-conditional-indent=-1
--suffix=none
--break-after-logical

View File

@ -569,6 +569,7 @@ SET(QGIS_CORE_SRCS
3d/qgs3drendererregistry.cpp
3d/qgsabstract3drenderer.cpp
fieldformatter/qgscheckboxfieldformatter.cpp
fieldformatter/qgsrangefieldformatter.cpp
fieldformatter/qgsdatetimefieldformatter.cpp
fieldformatter/qgsfallbackfieldformatter.cpp
@ -1290,6 +1291,7 @@ SET(QGIS_CORE_HDRS
3d/qgs3drendererregistry.h
3d/qgsabstract3drenderer.h
fieldformatter/qgscheckboxfieldformatter.h
fieldformatter/qgsrangefieldformatter.h
fieldformatter/qgsdatetimefieldformatter.h
fieldformatter/qgsfallbackfieldformatter.h

View File

@ -0,0 +1,89 @@
/***************************************************************************
qgscheckboxfieldformatter.cpp - QgsCheckBoxFieldFormatter
---------------------
begin : 23.09.2019
copyright : (C) 2019 by Denis Rouzaud
email : denis@opengis.ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <QObject>
#include "qgscheckboxfieldformatter.h"
#include "qgsvectorlayer.h"
#include "qgsapplication.h"
QString QgsCheckBoxFieldFormatter::id() const
{
return QStringLiteral( "CheckBox" );
}
QString QgsCheckBoxFieldFormatter::representValue( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value ) const
{
Q_UNUSED( cache )
/*
This follows this logic:
if field type is bool:
NULL => nullRepresentation
true => tr("true")
false => tr("false")
else
if cannot convert to string (like json integer list) => (invalid)
if == checkedstate => tr("true")
if == uncheckedstate => tr("false")
else (value.toString)
*/
bool isNull = value.isNull();
bool boolValue = false;
QString textValue = QgsApplication::nullRepresentation();
const QVariant::Type fieldType = layer->fields().at( fieldIndex ).type();
if ( fieldType == QVariant::Bool )
{
boolValue = value.toBool();
}
else
{
if ( !value.canConvert<QString>() )
{
isNull = true;
textValue = QObject::tr( "(invalid)" );
}
else
{
if ( config.contains( QStringLiteral( "CheckedState" ) ) && value.toString() == config[ QStringLiteral( "CheckedState" ) ].toString() )
{
boolValue = true;
}
else if ( config.contains( QStringLiteral( "UncheckedState" ) ) && value.toString() == config[ QStringLiteral( "UncheckedState" ) ].toString() )
{
boolValue = false;
}
else
{
isNull = true;
textValue = QStringLiteral( "(%1)" ).arg( value.toString() );
}
}
}
if ( isNull )
{
return textValue;
}
if ( boolValue )
return QObject::tr( "true" );
else
return QObject::tr( "false" );
}

View File

@ -0,0 +1,44 @@
/***************************************************************************
qgscheckboxfieldformatter.h - QgsCheckBoxFieldFormatter
---------------------
begin : 23.09.2019
copyright : (C) 2019 by Denis Rouzaud
email : denis@opengis.ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSCHECKBOXFIELDFORMATTER_H
#define QGSCHECKBOXFIELDFORMATTER_H
#include "qgis_core.h"
#include "qgsfieldformatter.h"
/**
* \ingroup core
* Field formatter for a checkbox field.
*
* \since QGIS 3.10
*/
class CORE_EXPORT QgsCheckBoxFieldFormatter : public QgsFieldFormatter
{
public:
/**
* Constructor for QgsCheckBoxFieldFormatter.
*/
QgsCheckBoxFieldFormatter() = default;
QString id() const override;
QString representValue( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value ) const override;
};
#endif // QGSCHECKBOXFIELDFORMATTER_H

View File

@ -20,9 +20,6 @@
#include "qgsvectorlayer.h"
#include "qgsvectordataprovider.h"
QgsFieldFormatter::QgsFieldFormatter() //NOLINT
{
}
QString QgsFieldFormatter::representValue( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value ) const
{

View File

@ -40,7 +40,11 @@ class QgsVectorLayer;
class CORE_EXPORT QgsFieldFormatter
{
public:
QgsFieldFormatter();
/**
* Default constructor
*/
QgsFieldFormatter() = default;
virtual ~QgsFieldFormatter() = default;

View File

@ -23,6 +23,7 @@
#include "qgskeyvaluefieldformatter.h"
#include "qgslistfieldformatter.h"
#include "qgsrangefieldformatter.h"
#include "qgscheckboxfieldformatter.h"
#include "qgsfallbackfieldformatter.h"
@ -36,6 +37,7 @@ QgsFieldFormatterRegistry::QgsFieldFormatterRegistry( QObject *parent )
addFieldFormatter( new QgsListFieldFormatter() );
addFieldFormatter( new QgsDateTimeFieldFormatter() );
addFieldFormatter( new QgsRangeFieldFormatter() );
addFieldFormatter( new QgsCheckBoxFieldFormatter() );
mFallbackFieldFormatter = new QgsFallbackFieldFormatter();
}

View File

@ -689,8 +689,11 @@ QVariant QgsAttributeTableModel::data( const QModelIndex &index, int role ) cons
{
case Qt::DisplayRole:
case Qt::ToolTipRole:
return mFieldFormatters.at( index.column() )->representValue( layer(), fieldId, mWidgetConfigs.at( index.column() ),
mAttributeWidgetCaches.at( index.column() ), val );
return mFieldFormatters.at( index.column() )->representValue( layer(),
fieldId,
mWidgetConfigs.at( index.column() ),
mAttributeWidgetCaches.at( index.column() ),
val );
case Qt::EditRole:
return val;

View File

@ -15,7 +15,7 @@ import qgis # NOQA
from qgis.core import (QgsFeature, QgsProject, QgsRelation, QgsVectorLayer,
QgsValueMapFieldFormatter, QgsValueRelationFieldFormatter,
QgsRelationReferenceFieldFormatter, QgsRangeFieldFormatter,
QgsSettings, QgsGeometry, QgsPointXY)
QgsCheckBoxFieldFormatter, QgsSettings, QgsGeometry, QgsPointXY)
from qgis.PyQt.QtCore import QCoreApplication, QLocale
from qgis.testing import start_app, unittest
@ -357,5 +357,39 @@ class TestQgsRangeFieldFormatter(unittest.TestCase):
QgsProject.instance().removeAllMapLayers()
class TestQgsCheckBoxFieldFormatter(unittest.TestCase):
@classmethod
def setUpClass(cls):
"""Run before all tests"""
QCoreApplication.setOrganizationName("QGIS_Test")
QCoreApplication.setOrganizationDomain("QGIS_TestPyQgsCheckBoxFieldFormatter.com")
QCoreApplication.setApplicationName("QGIS_TestPyQgsCheckBoxFieldFormatter")
QgsSettings().clear()
start_app()
def test_representValue(self):
null_value = "NULL"
QgsSettings().setValue("qgis/nullValue", null_value)
layer = QgsVectorLayer("point?field=int:integer&field=str:string", "layer", "memory")
self.assertTrue(layer.isValid())
field_formatter = QgsCheckBoxFieldFormatter()
# test with integer
# normal case
self.assertEqual(field_formatter.representValue(layer, 0, {'UncheckedState': 0, 'CheckedState': 1}, None, 1), 'true')
self.assertEqual(field_formatter.representValue(layer, 0, {'UncheckedState': 0, 'CheckedState': 1}, None, 0), 'false')
self.assertEqual(field_formatter.representValue(layer, 0, {'UncheckedState': 0, 'CheckedState': 1}, None, 10), "(10)")
# invert true/false
self.assertEqual(field_formatter.representValue(layer, 0, {'UncheckedState': 1, 'CheckedState': 0}, None, 0), 'true')
self.assertEqual(field_formatter.representValue(layer, 0, {'UncheckedState': 1, 'CheckedState': 0}, None, 1), 'false')
# test with string
self.assertEqual(field_formatter.representValue(layer, 1, {'UncheckedState': 'nooh', 'CheckedState': 'yeah'}, None, 'yeah'), 'true')
self.assertEqual(field_formatter.representValue(layer, 1, {'UncheckedState': 'nooh', 'CheckedState': 'yeah'}, None, 'nooh'), 'false')
self.assertEqual(field_formatter.representValue(layer, 1, {'UncheckedState': 'nooh', 'CheckedState': 'yeah'}, None, 'oops'), "(oops)")
if __name__ == '__main__':
unittest.main()