mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-07 00:15:48 -04:00
FIX #15144 add tooltip on fields in identify window / attribute window / feature form
- added new `QString QgsField::displayType( const bool showConstraints = false )` to unify the display of field types whenever length or precision are present - added new argument `expression` to `QgsFieldModel::fieldToolTip( const QgsField &field, const QString &expression = QStringLiteral() )`. Now the tooltip shows "<alias> (<field>)\n<type>\n<comment>\n<expression>" with appropriate formatting - added meaningful field tooltips in the "Identify Results" dialog - field tooltips show the same content in "Feature Attributes" form, "Attribute Table" and "Identify Tool" Fixes #15144
This commit is contained in:
parent
0e1eb51c2c
commit
050dfce89a
@ -104,6 +104,18 @@ represents.
|
||||
.. versionadded:: 3.12
|
||||
%End
|
||||
|
||||
|
||||
QString displayType( bool showConstraints = false ) const;
|
||||
%Docstring
|
||||
Returns the type to use when displaying this field, including the length and precision of the datatype if applicable.
|
||||
|
||||
This will be used when the full datatype with details has to displayed to the user.
|
||||
|
||||
.. seealso:: :py:func:`type`
|
||||
|
||||
.. versionadded:: 3.14
|
||||
%End
|
||||
|
||||
QVariant::Type type() const;
|
||||
%Docstring
|
||||
Gets variant type of the field as it will be retrieved from data source
|
||||
|
@ -128,7 +128,7 @@ Returns the layer associated with the model.
|
||||
virtual QVariant data( const QModelIndex &index, int role ) const;
|
||||
|
||||
|
||||
static QString fieldToolTip( const QgsField &field );
|
||||
static QString fieldToolTip( const QgsField &field, const QString &expression = QString() );
|
||||
%Docstring
|
||||
Returns a HTML formatted tooltip string for a ``field``, containing details
|
||||
like the field name, alias and type.
|
||||
|
@ -78,6 +78,7 @@
|
||||
#include "qgsfiledownloaderdialog.h"
|
||||
#include "qgsfieldformatterregistry.h"
|
||||
#include "qgsfieldformatter.h"
|
||||
#include "qgsfieldmodel.h"
|
||||
#include "qgssettings.h"
|
||||
#include "qgsgui.h"
|
||||
#include "qgsexpressioncontextutils.h"
|
||||
@ -625,8 +626,11 @@ void QgsIdentifyResultsDialog::addFeature( QgsVectorLayer *vlayer, const QgsFeat
|
||||
QgsTreeWidgetItem *attrItem = new QgsTreeWidgetItem( QStringList() << QString::number( i ) << value );
|
||||
featItem->addChild( attrItem );
|
||||
|
||||
QString expressionString = fields.fieldOrigin( i ) == QgsFields::OriginExpression
|
||||
? vlayer->expressionField( i )
|
||||
: QStringLiteral();
|
||||
attrItem->setData( 0, Qt::DisplayRole, vlayer->attributeDisplayName( i ) );
|
||||
attrItem->setToolTip( 0, vlayer->attributeDisplayName( i ) );
|
||||
attrItem->setToolTip( 0, QgsFieldModel::fieldToolTip( fields.at( i ), expressionString ) );
|
||||
attrItem->setData( 0, Qt::UserRole, fields.at( i ).name() );
|
||||
attrItem->setData( 0, Qt::UserRole + 1, i );
|
||||
|
||||
|
@ -103,6 +103,29 @@ QString QgsField::displayNameWithAlias() const
|
||||
return QStringLiteral( "%1 (%2)" ).arg( name() ).arg( alias() );
|
||||
}
|
||||
|
||||
QString QgsField::displayType( const bool showConstraints ) const
|
||||
{
|
||||
QString typeStr = typeName();
|
||||
|
||||
if ( length() > 0 && precision() > 0 )
|
||||
typeStr += QStringLiteral( "(%1, %2)" ).arg( length() ).arg( precision() );
|
||||
else if ( length() > 0 )
|
||||
typeStr += QStringLiteral( "(%1)" ).arg( length() );
|
||||
|
||||
if ( showConstraints )
|
||||
{
|
||||
typeStr += constraints().constraints() & QgsFieldConstraints::ConstraintNotNull
|
||||
? QStringLiteral( " NOT NULL" )
|
||||
: QStringLiteral( " NULL" );
|
||||
|
||||
typeStr += constraints().constraints() & QgsFieldConstraints::ConstraintUnique
|
||||
? QStringLiteral( " UNIQUE" )
|
||||
: QStringLiteral( "" );
|
||||
}
|
||||
|
||||
return typeStr;
|
||||
}
|
||||
|
||||
QVariant::Type QgsField::type() const
|
||||
{
|
||||
return d->type;
|
||||
|
@ -130,6 +130,17 @@ class CORE_EXPORT QgsField
|
||||
*/
|
||||
QString displayNameWithAlias() const;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the type to use when displaying this field, including the length and precision of the datatype if applicable.
|
||||
*
|
||||
* This will be used when the full datatype with details has to displayed to the user.
|
||||
*
|
||||
* \see type()
|
||||
* \since QGIS 3.14
|
||||
*/
|
||||
QString displayType( bool showConstraints = false ) const;
|
||||
|
||||
//! Gets variant type of the field as it will be retrieved from data source
|
||||
QVariant::Type type() const;
|
||||
|
||||
|
@ -464,7 +464,7 @@ QVariant QgsFieldModel::data( const QModelIndex &index, int role ) const
|
||||
}
|
||||
}
|
||||
|
||||
QString QgsFieldModel::fieldToolTip( const QgsField &field )
|
||||
QString QgsFieldModel::fieldToolTip( const QgsField &field, const QString &expression )
|
||||
{
|
||||
QString toolTip;
|
||||
if ( !field.alias().isEmpty() )
|
||||
@ -475,23 +475,21 @@ QString QgsFieldModel::fieldToolTip( const QgsField &field )
|
||||
{
|
||||
toolTip = QStringLiteral( "<b>%1</b>" ).arg( field.name() );
|
||||
}
|
||||
QString typeString;
|
||||
if ( field.length() > 0 )
|
||||
|
||||
toolTip += QStringLiteral( "<br><font style='font-family:monospace; white-space: nowrap;'>%3</font>" ).arg( field.displayType( true ) );
|
||||
|
||||
QString comment = field.comment();
|
||||
|
||||
if ( ! comment.isEmpty() )
|
||||
{
|
||||
if ( field.precision() > 0 )
|
||||
{
|
||||
typeString = QStringLiteral( "%1 (%2, %3)" ).arg( field.typeName() ).arg( field.length() ).arg( field.precision() );
|
||||
}
|
||||
else
|
||||
{
|
||||
typeString = QStringLiteral( "%1 (%2)" ).arg( field.typeName() ).arg( field.length() );
|
||||
}
|
||||
toolTip += QStringLiteral( "<br><em>%1</em>" ).arg( comment );
|
||||
}
|
||||
else
|
||||
|
||||
if ( ! expression.isEmpty() )
|
||||
{
|
||||
typeString = field.typeName();
|
||||
toolTip += QStringLiteral( "<br><font style='font-family:monospace;'>%3</font>" ).arg( expression );
|
||||
}
|
||||
toolTip += QStringLiteral( "<p>%1</p>" ).arg( typeString );
|
||||
|
||||
return toolTip;
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ class CORE_EXPORT QgsFieldModel : public QAbstractItemModel
|
||||
* like the field name, alias and type.
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
static QString fieldToolTip( const QgsField &field );
|
||||
static QString fieldToolTip( const QgsField &field, const QString &expression = QString() );
|
||||
|
||||
/**
|
||||
* Manually sets the \a fields to use for the model.
|
||||
|
@ -624,7 +624,10 @@ QVariant QgsAttributeTableModel::headerData( int section, Qt::Orientation orient
|
||||
else
|
||||
{
|
||||
const QgsField field = layer()->fields().at( mAttributes.at( section ) );
|
||||
return QgsFieldModel::fieldToolTip( field );
|
||||
QString expressionString = layer()->fields().fieldOrigin( mAttributes.at( section ) ) == QgsFields::OriginExpression
|
||||
? layer()->expressionField( mAttributes.at( section ) )
|
||||
: QStringLiteral();
|
||||
return QgsFieldModel::fieldToolTip( field, expressionString );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "qgsexpressioncontextutils.h"
|
||||
#include "qgsfeaturerequest.h"
|
||||
#include "qgstexteditwrapper.h"
|
||||
#include "qgsfieldmodel.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QTextStream>
|
||||
@ -1505,8 +1506,11 @@ void QgsAttributeForm::init()
|
||||
bool labelOnTop = mLayer->editFormConfig().labelOnTop( idx );
|
||||
|
||||
// This will also create the widget
|
||||
QString expressionString = fields.fieldOrigin( idx ) == QgsFields::OriginExpression
|
||||
? mLayer->expressionField( idx )
|
||||
: QStringLiteral();
|
||||
QLabel *l = new QLabel( labelText );
|
||||
l->setToolTip( QStringLiteral( "<b>%1</b><p>%2</p>" ).arg( fieldName, field.comment() ) );
|
||||
l->setToolTip( QgsFieldModel::fieldToolTip( field, expressionString ) );
|
||||
QSvgWidget *i = new QSvgWidget();
|
||||
i->setFixedSize( 18, 18 );
|
||||
|
||||
|
@ -48,6 +48,7 @@ class TestQgsField: public QObject
|
||||
void dataStream();
|
||||
void displayName();
|
||||
void displayNameWithAlias();
|
||||
void displayType();
|
||||
void editorWidgetSetup();
|
||||
void collection();
|
||||
|
||||
@ -752,6 +753,24 @@ void TestQgsField::displayNameWithAlias()
|
||||
}
|
||||
|
||||
|
||||
void TestQgsField::displayType()
|
||||
{
|
||||
QgsField field;
|
||||
field.setTypeName( QStringLiteral( "numeric" ) );
|
||||
QCOMPARE( field.displayType(), QString( "numeric" ) );
|
||||
field.setLength( 20 );
|
||||
QCOMPARE( field.displayType(), QString( "numeric(20)" ) );
|
||||
field.setPrecision( 10 );
|
||||
field.setPrecision( 10 );
|
||||
QCOMPARE( field.displayType(), QString( "numeric(20, 10)" ) );
|
||||
QCOMPARE( field.displayType( true ), QString( "numeric(20, 10) NULL" ) );
|
||||
QgsFieldConstraints constraints;
|
||||
constraints.setConstraint( QgsFieldConstraints::ConstraintUnique );
|
||||
field.setConstraints( constraints );
|
||||
QCOMPARE( field.displayType( true ), QString( "numeric(20, 10) NULL UNIQUE" ) );
|
||||
}
|
||||
|
||||
|
||||
void TestQgsField::editorWidgetSetup()
|
||||
{
|
||||
QgsField field;
|
||||
|
@ -19,7 +19,8 @@ from qgis.core import (QgsField,
|
||||
QgsFieldProxyModel,
|
||||
QgsEditorWidgetSetup,
|
||||
QgsProject,
|
||||
QgsVectorLayerJoinInfo)
|
||||
QgsVectorLayerJoinInfo,
|
||||
QgsFieldConstraints)
|
||||
from qgis.PyQt.QtCore import QVariant, Qt, QModelIndex
|
||||
|
||||
from qgis.testing import start_app, unittest
|
||||
@ -350,13 +351,21 @@ class TestQgsFieldModel(unittest.TestCase):
|
||||
|
||||
def testFieldTooltip(self):
|
||||
f = QgsField('my_string', QVariant.String, 'string')
|
||||
self.assertEqual(QgsFieldModel.fieldToolTip(f), '<b>my_string</b><p>string</p>')
|
||||
self.assertEqual(QgsFieldModel.fieldToolTip(f), "<b>my_string</b><br><font style='font-family:monospace; white-space: nowrap;'>string NULL</font>")
|
||||
f.setAlias('my alias')
|
||||
self.assertEqual(QgsFieldModel.fieldToolTip(f), '<b>my alias</b> (my_string)<p>string</p>')
|
||||
self.assertEqual(QgsFieldModel.fieldToolTip(f), "<b>my alias</b> (my_string)<br><font style='font-family:monospace; white-space: nowrap;'>string NULL</font>")
|
||||
f.setLength(20)
|
||||
self.assertEqual(QgsFieldModel.fieldToolTip(f), '<b>my alias</b> (my_string)<p>string (20)</p>')
|
||||
self.assertEqual(QgsFieldModel.fieldToolTip(f), "<b>my alias</b> (my_string)<br><font style='font-family:monospace; white-space: nowrap;'>string(20) NULL</font>")
|
||||
f = QgsField('my_real', QVariant.Double, 'real', 8, 3)
|
||||
self.assertEqual(QgsFieldModel.fieldToolTip(f), '<b>my_real</b><p>real (8, 3)</p>')
|
||||
self.assertEqual(QgsFieldModel.fieldToolTip(f), "<b>my_real</b><br><font style='font-family:monospace; white-space: nowrap;'>real(8, 3) NULL</font>")
|
||||
f.setComment('Comment text')
|
||||
self.assertEqual(QgsFieldModel.fieldToolTip(f), "<b>my_real</b><br><font style='font-family:monospace; white-space: nowrap;'>real(8, 3) NULL</font><br><em>Comment text</em>")
|
||||
self.assertEqual(QgsFieldModel.fieldToolTip(f, '1+1'), "<b>my_real</b><br><font style='font-family:monospace; white-space: nowrap;'>real(8, 3) NULL</font><br><em>Comment text</em><br><font style='font-family:monospace;'>1+1</font>")
|
||||
f.setAlias('my alias')
|
||||
constraints = f.constraints()
|
||||
constraints.setConstraint(QgsFieldConstraints.ConstraintUnique)
|
||||
f.setConstraints(constraints)
|
||||
self.assertEqual(QgsFieldModel.fieldToolTip(f, '1+1'), "<b>my alias</b> (my_real)<br><font style='font-family:monospace; white-space: nowrap;'>real(8, 3) NULL UNIQUE</font><br><em>Comment text</em><br><font style='font-family:monospace;'>1+1</font>")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Loading…
x
Reference in New Issue
Block a user