Skip to content

Commit 8aa160b

Browse files
committed
Add html support in map tips
- Add new display tab to edit html text
1 parent ddd3b27 commit 8aa160b

File tree

5 files changed

+375
-75
lines changed

5 files changed

+375
-75
lines changed

src/app/qgsvectorlayerproperties.cpp

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
9595
connect( layer, SIGNAL( attributeAdded( int ) ), this, SLOT( attributeAdded( int ) ) );
9696
connect( layer, SIGNAL( attributeDeleted( int ) ), this, SLOT( attributeDeleted( int ) ) );
9797

98+
connect( insertFieldButton, SIGNAL( clicked() ), this, SLOT( insertField() ) );
99+
connect( insertExpressionButton, SIGNAL( clicked() ), this, SLOT( insertExpression() ) );
100+
101+
98102
mAddAttributeButton->setIcon( QgsApplication::getThemeIcon( "/mActionNewAttribute.png" ) );
99103
mDeleteAttributeButton->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteAttribute.png" ) );
100104
mToggleEditingButton->setIcon( QgsApplication::getThemeIcon( "/mActionToggleEditing.png" ) );
@@ -481,9 +485,55 @@ void QgsVectorLayerProperties::setLegendType( QString type )
481485
legendtypecombobox->setItemText( legendtypecombobox->currentIndex(), type );
482486
}
483487

488+
void QgsVectorLayerProperties::insertField()
489+
{
490+
// Convert the selected field to an expression and
491+
// insert it into the action at the cursor position
492+
493+
if ( !fieldComboBox->currentText().isNull() )
494+
{
495+
QString field = "[% \"";
496+
field += fieldComboBox->currentText();
497+
field += "\" %]";
498+
htmlMapTip->insertPlainText( field );
499+
}
500+
}
501+
502+
void QgsVectorLayerProperties::insertExpression()
503+
{
504+
QString selText = htmlMapTip->textCursor().selectedText();
505+
506+
// edit the selected expression if there's one
507+
if ( selText.startsWith( "[%" ) && selText.endsWith( "%]" ) )
508+
selText = selText.mid( 2, selText.size() - 4 );
509+
510+
// display the expression builder
511+
QgsExpressionBuilderDialog dlg( layer , selText, this );
512+
dlg.setWindowTitle( tr( "Insert expression" ) );
513+
if ( dlg.exec() == QDialog::Accepted )
514+
{
515+
QString expression = dlg.expressionBuilder()->expressionText();
516+
//Only add the expression if the user has entered some text.
517+
if ( !expression.isEmpty() )
518+
{
519+
htmlMapTip->insertPlainText( "[%" + expression + "%]" );
520+
}
521+
}
522+
}
523+
484524
void QgsVectorLayerProperties::setDisplayField( QString name )
485525
{
486-
displayFieldComboBox->setItemText( displayFieldComboBox->currentIndex(), name );
526+
int idx = displayFieldComboBox->findText( name );
527+
if ( idx == -1 )
528+
{
529+
htmlRadio->setChecked( true );
530+
htmlMapTip->setPlainText( name );
531+
}
532+
else
533+
{
534+
fieldComboRadio->setChecked( true );
535+
displayFieldComboBox->setCurrentIndex( idx );
536+
}
487537
}
488538

489539
//! @note in raster props, this method is called sync()
@@ -520,9 +570,10 @@ void QgsVectorLayerProperties::reset( void )
520570
for ( QgsFieldMap::const_iterator it = myFields.begin(); it != myFields.end(); ++it )
521571
{
522572
displayFieldComboBox->addItem( it->name() );
573+
fieldComboBox->addItem( it->name() );
523574
}
524-
displayFieldComboBox->setCurrentIndex( displayFieldComboBox->findText(
525-
layer->displayField() ) );
575+
576+
setDisplayField( layer-> displayField() );
526577

527578
// set up the scale based layer visibility stuff....
528579
chkUseScaleDependentRendering->setChecked( layer->hasScaleBasedVisibility() );
@@ -633,7 +684,15 @@ void QgsVectorLayerProperties::apply()
633684
}
634685

635686
// update the display field
636-
layer->setDisplayField( displayFieldComboBox->currentText() );
687+
if ( htmlRadio->isChecked() )
688+
{
689+
layer->setDisplayField( htmlMapTip->toPlainText() );
690+
}
691+
692+
if ( fieldComboRadio->isChecked() )
693+
{
694+
layer->setDisplayField( displayFieldComboBox->currentText() );
695+
}
637696

638697
layer->setEditForm( leEditForm->text() );
639698
layer->setEditFormInit( leEditFormInit->text() );

src/app/qgsvectorlayerproperties.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "qgsfield.h"
2929
#include "qgsmapcanvas.h"
3030
#include "qgscontexthelp.h"
31+
#include "qgsexpressionbuilderdialog.h"
3132

3233
class QgsMapLayer;
3334

@@ -55,6 +56,7 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
5556
/**Returns the display name entered in the dialog*/
5657
QString displayName();
5758
void setRendererDirty( bool ) {}
59+
5860
/**Sets the attribute that is used in the Identify Results dialog box*/
5961
void setDisplayField( QString name );
6062

@@ -70,6 +72,11 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
7072

7173
public slots:
7274

75+
/** Insert a field in the expression text for the map tip **/
76+
void insertField();
77+
78+
void insertExpression();
79+
7380
void attributeTypeDialog();
7481

7582
void alterLayerDialog( const QString& string );

src/gui/qgsmaptip.cpp

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
* *
1414
***************************************************************************/
1515
// QGIS includes
16-
#include <qgsmapcanvas.h>
17-
#include <qgsvectorlayer.h>
16+
#include "qgsmapcanvas.h"
17+
#include "qgsvectorlayer.h"
18+
#include "qgsexpression.h"
19+
#include "qgslogger.h"
1820

1921
// Qt includes
2022
#include <QPoint>
@@ -91,15 +93,59 @@ QString QgsMapTip::fetchFeature( QgsMapLayer *layer, QgsPoint &mapPosition, QgsM
9193

9294
r = mpMapCanvas->mapRenderer()->mapToLayerCoordinates( layer, r );
9395

94-
int idx = vlayer->fieldNameIndex( vlayer->displayField() );
95-
if ( idx < 0 )
96-
return "";
97-
9896
QgsFeature feature;
9997

100-
vlayer->select( QgsAttributeList() << idx, r, true, true );
98+
vlayer->select( vlayer->pendingAllAttributesList() , r, true, true );
10199
if ( !vlayer->nextFeature( feature ) )
102100
return "";
103101

104-
return feature.attributeMap().value( idx, "" ).toString();
102+
int idx = vlayer->fieldNameIndex( vlayer->displayField() );
103+
if ( idx < 0 )
104+
return replaceText( vlayer->displayField(), vlayer, feature );
105+
else
106+
return feature.attributeMap().value( idx, "" ).toString();
107+
108+
}
109+
110+
QString QgsMapTip::replaceText( QString displayText, QgsVectorLayer *layer, QgsFeature &feat )
111+
{
112+
QString expr_action;
113+
114+
int index = 0;
115+
while ( index < displayText.size() )
116+
{
117+
QRegExp rx = QRegExp( "\\[%([^\\]]+)%\\]" );
118+
119+
int pos = rx.indexIn( displayText, index );
120+
if ( pos < 0 )
121+
break;
122+
123+
int start = index;
124+
index = pos + rx.matchedLength();
125+
126+
QString to_replace = rx.cap( 1 ).trimmed();
127+
QgsDebugMsg( "Found expression: " + to_replace );
128+
129+
QgsExpression exp( to_replace );
130+
if ( exp.hasParserError() )
131+
{
132+
QgsDebugMsg( "Expression parser error: " + exp.parserErrorString() );
133+
expr_action += displayText.mid( start, index - start );
134+
continue;
135+
}
136+
137+
QVariant result = exp.evaluate( &feat, layer->pendingFields() );
138+
if ( exp.hasEvalError() )
139+
{
140+
QgsDebugMsg( "Expression parser eval error: " + exp.evalErrorString() );
141+
expr_action += displayText.mid( start, index - start );
142+
continue;
143+
}
144+
145+
QgsDebugMsg( "Expression result is: " + result.toString() );
146+
expr_action += displayText.mid( start, pos - start ) + result.toString();
147+
}
148+
149+
expr_action += displayText.mid( index );
150+
return expr_action;
105151
}

src/gui/qgsmaptip.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class QgsMapCanvas;
2020
class QPoint;
2121
class QString;
2222

23+
#include "qgsfeature.h"
2324

2425
/** \ingroup gui
2526
* A maptip is a class to display a tip on a map canvas
@@ -57,6 +58,9 @@ class GUI_EXPORT QgsMapTip
5758
QString fetchFeature( QgsMapLayer * thepLayer,
5859
QgsPoint & theMapPosition,
5960
QgsMapCanvas *thepMapCanvas );
61+
62+
QString replaceText( QString displayText, QgsVectorLayer *layer, QgsFeature &feat );
63+
6064
// Flag to indicate if a maptip is currently being displayed
6165
bool mMapTipVisible;
6266
// Last point on the map canvas when the maptip timer fired. This point is in widget pixel

0 commit comments

Comments
 (0)