Skip to content
Permalink
Browse files
Add html support in map tips
 - Add new display tab to edit html text
  • Loading branch information
NathanW2 committed Aug 5, 2012
1 parent ddd3b27 commit 8aa160bcb3548a881248c7d46d92c4f2e12ffc02
Showing with 375 additions and 75 deletions.
  1. +63 −4 src/app/qgsvectorlayerproperties.cpp
  2. +7 −0 src/app/qgsvectorlayerproperties.h
  3. +54 −8 src/gui/qgsmaptip.cpp
  4. +4 −0 src/gui/qgsmaptip.h
  5. +247 −63 src/ui/qgsvectorlayerpropertiesbase.ui
@@ -95,6 +95,10 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
connect( layer, SIGNAL( attributeAdded( int ) ), this, SLOT( attributeAdded( int ) ) );
connect( layer, SIGNAL( attributeDeleted( int ) ), this, SLOT( attributeDeleted( int ) ) );

connect( insertFieldButton, SIGNAL( clicked() ), this, SLOT( insertField() ) );
connect( insertExpressionButton, SIGNAL( clicked() ), this, SLOT( insertExpression() ) );


mAddAttributeButton->setIcon( QgsApplication::getThemeIcon( "/mActionNewAttribute.png" ) );
mDeleteAttributeButton->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteAttribute.png" ) );
mToggleEditingButton->setIcon( QgsApplication::getThemeIcon( "/mActionToggleEditing.png" ) );
@@ -481,9 +485,55 @@ void QgsVectorLayerProperties::setLegendType( QString type )
legendtypecombobox->setItemText( legendtypecombobox->currentIndex(), type );
}

void QgsVectorLayerProperties::insertField()
{
// Convert the selected field to an expression and
// insert it into the action at the cursor position

if ( !fieldComboBox->currentText().isNull() )
{
QString field = "[% \"";
field += fieldComboBox->currentText();
field += "\" %]";
htmlMapTip->insertPlainText( field );
}
}

void QgsVectorLayerProperties::insertExpression()
{
QString selText = htmlMapTip->textCursor().selectedText();

// edit the selected expression if there's one
if ( selText.startsWith( "[%" ) && selText.endsWith( "%]" ) )
selText = selText.mid( 2, selText.size() - 4 );

// display the expression builder
QgsExpressionBuilderDialog dlg( layer , selText, this );
dlg.setWindowTitle( tr( "Insert expression" ) );
if ( dlg.exec() == QDialog::Accepted )
{
QString expression = dlg.expressionBuilder()->expressionText();
//Only add the expression if the user has entered some text.
if ( !expression.isEmpty() )
{
htmlMapTip->insertPlainText( "[%" + expression + "%]" );
}
}
}

void QgsVectorLayerProperties::setDisplayField( QString name )
{
displayFieldComboBox->setItemText( displayFieldComboBox->currentIndex(), name );
int idx = displayFieldComboBox->findText( name );
if ( idx == -1 )
{
htmlRadio->setChecked( true );
htmlMapTip->setPlainText( name );
}
else
{
fieldComboRadio->setChecked( true );
displayFieldComboBox->setCurrentIndex( idx );
}
}

//! @note in raster props, this method is called sync()
@@ -520,9 +570,10 @@ void QgsVectorLayerProperties::reset( void )
for ( QgsFieldMap::const_iterator it = myFields.begin(); it != myFields.end(); ++it )
{
displayFieldComboBox->addItem( it->name() );
fieldComboBox->addItem( it->name() );
}
displayFieldComboBox->setCurrentIndex( displayFieldComboBox->findText(
layer->displayField() ) );

setDisplayField( layer-> displayField() );

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

// update the display field
layer->setDisplayField( displayFieldComboBox->currentText() );
if ( htmlRadio->isChecked() )
{
layer->setDisplayField( htmlMapTip->toPlainText() );
}

if ( fieldComboRadio->isChecked() )
{
layer->setDisplayField( displayFieldComboBox->currentText() );
}

layer->setEditForm( leEditForm->text() );
layer->setEditFormInit( leEditFormInit->text() );
@@ -28,6 +28,7 @@
#include "qgsfield.h"
#include "qgsmapcanvas.h"
#include "qgscontexthelp.h"
#include "qgsexpressionbuilderdialog.h"

class QgsMapLayer;

@@ -55,6 +56,7 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
/**Returns the display name entered in the dialog*/
QString displayName();
void setRendererDirty( bool ) {}

/**Sets the attribute that is used in the Identify Results dialog box*/
void setDisplayField( QString name );

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

public slots:

/** Insert a field in the expression text for the map tip **/
void insertField();

void insertExpression();

void attributeTypeDialog();

void alterLayerDialog( const QString& string );
@@ -13,8 +13,10 @@
* *
***************************************************************************/
// QGIS includes
#include <qgsmapcanvas.h>
#include <qgsvectorlayer.h>
#include "qgsmapcanvas.h"
#include "qgsvectorlayer.h"
#include "qgsexpression.h"
#include "qgslogger.h"

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

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

int idx = vlayer->fieldNameIndex( vlayer->displayField() );
if ( idx < 0 )
return "";

QgsFeature feature;

vlayer->select( QgsAttributeList() << idx, r, true, true );
vlayer->select( vlayer->pendingAllAttributesList() , r, true, true );
if ( !vlayer->nextFeature( feature ) )
return "";

return feature.attributeMap().value( idx, "" ).toString();
int idx = vlayer->fieldNameIndex( vlayer->displayField() );
if ( idx < 0 )
return replaceText( vlayer->displayField(), vlayer, feature );
else
return feature.attributeMap().value( idx, "" ).toString();

}

QString QgsMapTip::replaceText( QString displayText, QgsVectorLayer *layer, QgsFeature &feat )
{
QString expr_action;

int index = 0;
while ( index < displayText.size() )
{
QRegExp rx = QRegExp( "\\[%([^\\]]+)%\\]" );

int pos = rx.indexIn( displayText, index );
if ( pos < 0 )
break;

int start = index;
index = pos + rx.matchedLength();

QString to_replace = rx.cap( 1 ).trimmed();
QgsDebugMsg( "Found expression: " + to_replace );

QgsExpression exp( to_replace );
if ( exp.hasParserError() )
{
QgsDebugMsg( "Expression parser error: " + exp.parserErrorString() );
expr_action += displayText.mid( start, index - start );
continue;
}

QVariant result = exp.evaluate( &feat, layer->pendingFields() );
if ( exp.hasEvalError() )
{
QgsDebugMsg( "Expression parser eval error: " + exp.evalErrorString() );
expr_action += displayText.mid( start, index - start );
continue;
}

QgsDebugMsg( "Expression result is: " + result.toString() );
expr_action += displayText.mid( start, pos - start ) + result.toString();
}

expr_action += displayText.mid( index );
return expr_action;
}
@@ -20,6 +20,7 @@ class QgsMapCanvas;
class QPoint;
class QString;

#include "qgsfeature.h"

/** \ingroup gui
* A maptip is a class to display a tip on a map canvas
@@ -57,6 +58,9 @@ class GUI_EXPORT QgsMapTip
QString fetchFeature( QgsMapLayer * thepLayer,
QgsPoint & theMapPosition,
QgsMapCanvas *thepMapCanvas );

QString replaceText( QString displayText, QgsVectorLayer *layer, QgsFeature &feat );

// Flag to indicate if a maptip is currently being displayed
bool mMapTipVisible;
// Last point on the map canvas when the maptip timer fired. This point is in widget pixel
Loading

2 comments on commit 8aa160b

@AndrewM-

This comment has been minimized.

Copy link

@AndrewM- AndrewM- replied Feb 28, 2014

Hi Nathan,
I cannot get the img display working. Can you please document the types of image paths that map tips can support. I have tried about a dozen variations on image URLs for displaying images in maptips without success. I am using GGIS 2.2 on a Win64 system. The image addresses that I would like to display look like this - 'H:\Photos\NonWork\2012-04-20_RedCliffPoint\Thumbs\P1190276.JPG'.

@AndrewM-

This comment has been minimized.

Copy link

@AndrewM- AndrewM- replied Mar 3, 2014

Correction, the maptips do work with images e.g.[img src=''H:\Photos\NonWork\2012-04-20_RedCliffPoint\Thumbs\P1190276.JPG"/] with angle brakets. However if you see text instead of an image, then the problem is probably text before or after the line with the image link. I found that putting
tags on either side of the above line to separate the image from other content made things work.

Please sign in to comment.