Skip to content

Commit 2cf9243

Browse files
authoredAug 2, 2016
Split displayField into displayExpression and mapTipTemplate (#1973)
Previously there was the expressionField (a field name or an expression) mainly used for the feature list in the form view of the dual view. On the other hand there was the displayField which could contain either a simple field name or a complex HTML structure with embedded expressions. And to know what it was you could compare it's content with the field names, if a field name matched, you used it as a displayField (original purpose) and if not... well, you could deal with HTML if you had a use for it. The main problem is that there are two different usages for this kind of thing * plain text identifier (field or expression) * pretty, rich text feature info This commit cleans up with this. You want rich text and a lot of info: go for mapTipTemplate. You want a plain text string to identify features: go for the displayExpression.
1 parent 2134112 commit 2cf9243

14 files changed

+365
-483
lines changed
 

‎doc/api_break.dox

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,8 @@ plugins calling this method will need to be updated.</li>
483483
setExcludeAttributesWms()</li>
484484
<li>excludeAttributesWFS() and setExcludeAttributesWFS() have been renamed to excludeAttributesWfs() and
485485
setExcludeAttributesWfs()</li>
486+
<li>The displayField property has been separated from the mapTip. For a plain text short title use the
487+
displayExpression instead. For the map tip use mapTipTemplate() instead.</li>
486488
<li>changeGeometry() now accepts a geometry reference, not a pointer.</li>
487489
<li>The geometryChanged() signal now uses a const QgsGeometry reference.</li>
488490
<li>The deprecated removePolygonIntersections has been removed.</li>

‎python/core/qgsvectorlayer.sip

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,14 @@ class QgsVectorLayer : QgsMapLayer
187187
/** Returns a comment for the data in the layer */
188188
QString dataComment() const;
189189

190-
/** Set the primary display field to be used in the identify results dialog */
191-
void setDisplayField( const QString& fldName = "" );
192-
193-
/** Returns the primary display field name used in the identify results dialog */
194-
const QString displayField() const;
190+
/**
191+
* This is a shorthand for accessing the displayExpression if it is a simple field.
192+
* If the displayExpression is more complex than a simple field, a null string will
193+
* be returned.
194+
*
195+
* @see displayExpression
196+
*/
197+
QString displayField() const;
195198

196199
/** Set the preview expression, used to create a human readable preview string.
197200
* Used e.g. in the attribute table feature list. Uses { @link QgsExpression }.
@@ -1414,6 +1417,24 @@ class QgsVectorLayer : QgsMapLayer
14141417
*/
14151418
void setAttributeTableConfig( const QgsAttributeTableConfig& attributeTableConfig );
14161419

1420+
/**
1421+
* The mapTip is a pretty, html representation for feature information.
1422+
*
1423+
* It may also contain embedded expressions.
1424+
*
1425+
* @note added in 3.0
1426+
*/
1427+
QString mapTipTemplate() const;
1428+
1429+
/**
1430+
* The mapTip is a pretty, html representation for feature information.
1431+
*
1432+
* It may also contain embedded expressions.
1433+
*
1434+
* @note added in 3.0
1435+
*/
1436+
void setMapTipTemplate( const QString& mapTipTemplate );
1437+
14171438
public slots:
14181439
/**
14191440
* Select feature by its ID
@@ -1675,6 +1696,20 @@ class QgsVectorLayer : QgsMapLayer
16751696
*/
16761697
void writeCustomSymbology( QDomElement& element, QDomDocument& doc, QString& errorMessage ) const;
16771698

1699+
/**
1700+
* Emitted when the map tip changes
1701+
*
1702+
* @note added in 3.0
1703+
*/
1704+
void mapTipTemplateChanged();
1705+
1706+
/**
1707+
* Emitted when the display expression changes
1708+
*
1709+
* @note added in 3.0
1710+
*/
1711+
void displayExpressionChanged();
1712+
16781713
/**
16791714
* Signals an error related to this vector layer.
16801715
*/

‎src/app/qgisapp.cpp

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3150,6 +3150,8 @@ void QgisApp::createMapTips()
31503150
connect( mpMapTipsTimer, SIGNAL( timeout() ), this, SLOT( showMapTip() ) );
31513151
// set the interval to 0.850 seconds - timer will be started next time the mouse moves
31523152
mpMapTipsTimer->setInterval( 850 );
3153+
mpMapTipsTimer->setSingleShot( true );
3154+
31533155
// Create the maptips object
31543156
mpMaptip = new QgsMapTip();
31553157
}
@@ -10158,33 +10160,22 @@ void QgisApp::removeMapToolMessage()
1015810160
// Show the maptip using tooltip
1015910161
void QgisApp::showMapTip()
1016010162
{
10161-
// Stop the timer while we look for a maptip
10162-
mpMapTipsTimer->stop();
10163+
QPoint myPointerPos = mMapCanvas->mouseLastXY();
1016310164

10164-
// Only show tooltip if the mouse is over the canvas
10165-
if ( mMapCanvas->underMouse() )
10165+
// Make sure there is an active layer before proceeding
10166+
QgsMapLayer* mypLayer = mMapCanvas->currentLayer();
10167+
if ( mypLayer )
1016610168
{
10167-
QPoint myPointerPos = mMapCanvas->mouseLastXY();
10168-
10169-
// Make sure there is an active layer before proceeding
10170-
QgsMapLayer* mypLayer = mMapCanvas->currentLayer();
10171-
if ( mypLayer )
10169+
//QgsDebugMsg("Current layer for maptip display is: " + mypLayer->source());
10170+
// only process vector layers
10171+
if ( mypLayer->type() == QgsMapLayer::VectorLayer )
1017210172
{
10173-
//QgsDebugMsg("Current layer for maptip display is: " + mypLayer->source());
10174-
// only process vector layers
10175-
if ( mypLayer->type() == QgsMapLayer::VectorLayer )
10173+
// Show the maptip if the maptips button is depressed
10174+
if ( mMapTipsVisible )
1017610175
{
10177-
// Show the maptip if the maptips button is depressed
10178-
if ( mMapTipsVisible )
10179-
{
10180-
mpMaptip->showMapTip( mypLayer, mLastMapPosition, myPointerPos, mMapCanvas );
10181-
}
10176+
mpMaptip->showMapTip( mypLayer, mLastMapPosition, myPointerPos, mMapCanvas );
1018210177
}
1018310178
}
10184-
else
10185-
{
10186-
showStatusMessage( tr( "Maptips require an active layer" ) );
10187-
}
1018810179
}
1018910180
}
1019010181

‎src/app/qgsidentifyresultsdialog.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -473,10 +473,11 @@ void QgsIdentifyResultsDialog::addFeature( QgsVectorLayer *vlayer, const QgsFeat
473473
const QgsFields &fields = vlayer->fields();
474474
QgsAttributes attrs = f.attributes();
475475
bool featureLabeled = false;
476+
476477
for ( int i = 0; i < attrs.count(); ++i )
477478
{
478479
if ( i >= fields.count() )
479-
continue;
480+
break;
480481

481482
if ( vlayer->editFormConfig()->widgetType( i ) == "Hidden" )
482483
{
@@ -524,8 +525,14 @@ void QgsIdentifyResultsDialog::addFeature( QgsVectorLayer *vlayer, const QgsFeat
524525

525526
if ( !featureLabeled )
526527
{
527-
featItem->setText( 0, tr( "feature id" ) );
528-
featItem->setText( 1, QString::number( f.id() ) );
528+
featItem->setText( 0, tr( "Title" ) );
529+
QgsExpressionContext context;
530+
context << QgsExpressionContextUtils::globalScope()
531+
<< QgsExpressionContextUtils::projectScope()
532+
<< QgsExpressionContextUtils::layerScope( vlayer );
533+
context.setFeature( f );
534+
535+
featItem->setText( 1, QgsExpression( vlayer->displayExpression() ).evaluate( &context ).toString() );
529536
}
530537

531538
// table

‎src/app/qgsvectorlayerproperties.cpp

Lines changed: 26 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -111,17 +111,18 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
111111

112112
connect( mOptionsStackedWidget, SIGNAL( currentChanged( int ) ), this, SLOT( mOptionsStackedWidget_CurrentChanged( int ) ) );
113113

114-
fieldComboBox->setLayer( lyr );
115-
displayFieldComboBox->setLayer( lyr );
116-
connect( insertFieldButton, SIGNAL( clicked() ), this, SLOT( insertField() ) );
117-
connect( insertExpressionButton, SIGNAL( clicked() ), this, SLOT( insertExpression() ) );
118-
119-
// connections for Map Tip display
120-
connect( htmlRadio, SIGNAL( toggled( bool ) ), htmlMapTip, SLOT( setEnabled( bool ) ) );
121-
connect( htmlRadio, SIGNAL( toggled( bool ) ), insertFieldButton, SLOT( setEnabled( bool ) ) );
122-
connect( htmlRadio, SIGNAL( toggled( bool ) ), fieldComboBox, SLOT( setEnabled( bool ) ) );
123-
connect( htmlRadio, SIGNAL( toggled( bool ) ), insertExpressionButton, SLOT( setEnabled( bool ) ) );
124-
connect( fieldComboRadio, SIGNAL( toggled( bool ) ), displayFieldComboBox, SLOT( setEnabled( bool ) ) );
114+
mContext << QgsExpressionContextUtils::globalScope()
115+
<< QgsExpressionContextUtils::projectScope()
116+
<< QgsExpressionContextUtils::atlasScope( nullptr )
117+
<< QgsExpressionContextUtils::mapSettingsScope( QgisApp::instance()->mapCanvas()->mapSettings() )
118+
<< QgsExpressionContextUtils::layerScope( mLayer );
119+
120+
mMapTipExpressionFieldWidget->setLayer( lyr );
121+
mMapTipExpressionFieldWidget->registerGetExpressionContextCallback( &_getExpressionContext, this );
122+
mDisplayExpressionWidget->setLayer( lyr );
123+
mDisplayExpressionWidget->registerGetExpressionContextCallback( &_getExpressionContext, this );
124+
125+
connect( mInsertExpressionButton, SIGNAL( clicked() ), this, SLOT( insertFieldOrExpression() ) );
125126

126127
if ( !mLayer )
127128
return;
@@ -326,57 +327,15 @@ void QgsVectorLayerProperties::addPropertiesPageFactory( QgsMapLayerConfigWidget
326327
mOptionsStackedWidget->addWidget( page );
327328
}
328329

329-
void QgsVectorLayerProperties::insertField()
330+
void QgsVectorLayerProperties::insertFieldOrExpression()
330331
{
331332
// Convert the selected field to an expression and
332333
// insert it into the action at the cursor position
333-
QString field = "[% \"";
334-
field += fieldComboBox->currentField();
335-
field += "\" %]";
336-
htmlMapTip->insertPlainText( field );
337-
}
338-
339-
void QgsVectorLayerProperties::insertExpression()
340-
{
341-
QString selText = htmlMapTip->textCursor().selectedText();
342-
343-
// edit the selected expression if there's one
344-
if ( selText.startsWith( "[%" ) && selText.endsWith( "%]" ) )
345-
selText = selText.mid( 2, selText.size() - 4 );
346-
347-
// display the expression builder
348-
QgsExpressionContext context;
349-
context << QgsExpressionContextUtils::globalScope()
350-
<< QgsExpressionContextUtils::projectScope()
351-
<< QgsExpressionContextUtils::atlasScope( nullptr )
352-
<< QgsExpressionContextUtils::mapSettingsScope( QgisApp::instance()->mapCanvas()->mapSettings() )
353-
<< QgsExpressionContextUtils::layerScope( mLayer );
354-
355-
QgsExpressionBuilderDialog dlg( mLayer, selText.replace( QChar::ParagraphSeparator, '\n' ), this, "generic", context );
356-
dlg.setWindowTitle( tr( "Insert expression" ) );
357-
if ( dlg.exec() == QDialog::Accepted )
358-
{
359-
QString expression = dlg.expressionBuilder()->expressionText();
360-
//Only add the expression if the user has entered some text.
361-
if ( !expression.isEmpty() )
362-
{
363-
htmlMapTip->insertPlainText( "[%" + expression + "%]" );
364-
}
365-
}
366-
}
334+
QString expression = "[% \"";
335+
expression += mMapTipExpressionFieldWidget->asExpression();
336+
expression += "\" %]";
367337

368-
void QgsVectorLayerProperties::setDisplayField( const QString& name )
369-
{
370-
if ( mLayer->fields().fieldNameIndex( name ) == -1 )
371-
{
372-
htmlRadio->setChecked( true );
373-
htmlMapTip->setPlainText( name );
374-
}
375-
else
376-
{
377-
fieldComboRadio->setChecked( true );
378-
displayFieldComboBox->setField( name );
379-
}
338+
mMapTipWidget->insertText( expression );
380339
}
381340

382341
//! @note in raster props, this method is called sync()
@@ -403,7 +362,8 @@ void QgsVectorLayerProperties::syncToLayer()
403362
txtSubsetSQL->setEnabled( false );
404363
setPbnQueryBuilderEnabled();
405364

406-
setDisplayField( mLayer->displayField() );
365+
mMapTipWidget->setText( mLayer->mapTipTemplate() );
366+
mDisplayExpressionWidget->setField( mLayer->displayExpression() );
407367

408368
// set up the scale based layer visibility stuff....
409369
mScaleRangeWidget->setScaleRange( 1.0 / mLayer->maximumScale(), 1.0 / mLayer->minimumScale() ); // caution: layer uses scale denoms, widget uses true scales
@@ -513,16 +473,8 @@ void QgsVectorLayerProperties::apply()
513473
}
514474
}
515475

516-
// update the display field
517-
if ( htmlRadio->isChecked() )
518-
{
519-
mLayer->setDisplayField( htmlMapTip->toPlainText() );
520-
}
521-
522-
if ( fieldComboRadio->isChecked() )
523-
{
524-
mLayer->setDisplayField( displayFieldComboBox->currentField() );
525-
}
476+
mLayer->setDisplayExpression( mDisplayExpressionWidget->currentField() );
477+
mLayer->setMapTipTemplate( mMapTipWidget->text() );
526478

527479
mLayer->actions()->clearActions();
528480
Q_FOREACH ( const QgsAction& action, mActionDialog->actions() )
@@ -1214,6 +1166,11 @@ void QgsVectorLayerProperties::addJoinToTreeWidget( const QgsVectorJoinInfo& joi
12141166
mJoinTreeWidget->setCurrentItem( joinItem );
12151167
}
12161168

1169+
QgsExpressionContext QgsVectorLayerProperties::_getExpressionContext( const void* context )
1170+
{
1171+
return static_cast<const QgsVectorLayerProperties*>( context )->mContext;
1172+
}
1173+
12171174
void QgsVectorLayerProperties::openPanel( QgsPanelWidget *panel )
12181175
{
12191176
QDialog* dlg = new QDialog();

‎src/app/qgsvectorlayerproperties.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,6 @@ class APP_EXPORT QgsVectorLayerProperties : public QgsOptionsDialogBase, private
5757
QString displayName();
5858
void setRendererDirty( bool ) {}
5959

60-
/** Sets the attribute that is used in the Identify Results dialog box*/
61-
void setDisplayField( const QString& name );
62-
6360
/** Adds an attribute to the table (but does not commit it yet)
6461
@param field the field to add
6562
@return false in case of a name conflict, true in case of success */
@@ -75,10 +72,7 @@ class APP_EXPORT QgsVectorLayerProperties : public QgsOptionsDialogBase, private
7572

7673
public slots:
7774

78-
/** Insert a field in the expression text for the map tip **/
79-
void insertField();
80-
81-
void insertExpression();
75+
void insertFieldOrExpression();
8276

8377
/** Reset to original (vector layer) values */
8478
void syncToLayer();
@@ -146,7 +140,7 @@ class APP_EXPORT QgsVectorLayerProperties : public QgsOptionsDialogBase, private
146140
*/
147141
void updateFieldsPropertiesDialog();
148142

149-
protected:
143+
private:
150144

151145
void saveStyleAs( StyleType styleType );
152146

@@ -195,6 +189,10 @@ class APP_EXPORT QgsVectorLayerProperties : public QgsOptionsDialogBase, private
195189
/** Adds a new join to mJoinTreeWidget*/
196190
void addJoinToTreeWidget( const QgsVectorJoinInfo& join , const int insertIndex = -1 );
197191

192+
QgsExpressionContext mContext;
193+
194+
static QgsExpressionContext _getExpressionContext( const void* context );
195+
198196
private slots:
199197
void openPanel( QgsPanelWidget* panel );
200198
};

0 commit comments

Comments
 (0)