35using namespace Qt::StringLiterals;
42#include <QDesktopServices>
46#include "moc_qgsmaptip.cpp"
49const QString QgsMapTip::sMapTipTemplate =
"<html>\n"
54 " font: %1pt \"%2\";\n"
58 " #QgsWebViewContainer {\n"
59 " background-color: %5;\n"
60 " border: 1px solid %6;\n"
61 " display: inline-block;\n"
64 " #QgsWebViewContainerInner {\n"
70 " <div id='QgsWebViewContainer'>\n"
71 " <div id='QgsWebViewContainerInner'>\n"
82 mMapTipVisible =
false;
84 mDelayedClearTimer.setSingleShot(
true );
85 connect( &mDelayedClearTimer, &QTimer::timeout,
this, [
this]() { this->
clear(); } );
97 if ( !pMapCanvas->
layers(
true ).contains( pLayer ) )
103 if ( mWebView && mWebView->underMouse() )
109 QString tipText, lastTipText, tipHtml;
114 mWebView->setOpenExternalLinks(
true );
119 QColor transparentColor = mWebView->palette().color( QPalette::Window );
120 transparentColor.setAlpha( 0 );
121 mWebView->setStyleSheet( QString(
"background:%1;" ).arg( transparentColor.name( QColor::HexArgb ) ) );
123 mWebView->page()->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled,
true );
124 mWebView->page()->settings()->setAttribute( QWebSettings::JavascriptEnabled,
true );
125 mWebView->page()->settings()->setAttribute( QWebSettings::LocalStorageEnabled,
true );
128 mWebView->page()->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
129 mWebView->page()->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );
133 switch ( pLayer->
type() )
136 tipText = fetchFeature( pLayer, mapPosition, pMapCanvas );
139 tipText = fetchRaster( pLayer, mapPosition, pMapCanvas );
145 mMapTipVisible = !tipText.isEmpty();
146 if ( !mMapTipVisible )
152 if ( tipText == lastTipText )
158 int cursorOffset = 0;
165 cursorOffset =
static_cast<int>( std::ceil( scale * 32 ) );
169 const int MAX_WIDTH = std::max( pixelPosition.x(), pMapCanvas->width() - pixelPosition.x() ) - cursorOffset - 5;
170 const int MAX_HEIGHT = std::max( pixelPosition.y(), pMapCanvas->height() - pixelPosition.y() ) - 5;
172 mWebView->setMaximumSize( MAX_WIDTH, MAX_HEIGHT );
174 tipHtml = QgsMapTip::htmlText( tipText, MAX_WIDTH );
178 mPosition = pixelPosition;
179 mMapCanvas = pMapCanvas;
180 mWebView->setHtml( tipHtml );
181 lastTipText = tipText;
183 resizeAndMoveToolTip();
186void QgsMapTip::resizeAndMoveToolTip()
188 mWebView->adjustSize();
190 int cursorOffset = 0;
198 cursorOffset =
static_cast<int>( std::ceil( scale * 32 ) );
203 mWebView->move( mPosition );
209 int availableWidthRight = mMapCanvas->width() - mPosition.x() - cursorOffset;
210 int availableWidthLeft = mPosition.x() - cursorOffset;
211 int availableHeightBottom = mMapCanvas->height() - mPosition.y();
212 int availableHeightTop = mPosition.y();
215 if ( mWebView->width() < availableWidthRight || availableWidthRight > availableWidthLeft )
217 x = mPosition.x() + cursorOffset;
222 x = mPosition.x() - mWebView->width() - cursorOffset;
226 if ( mWebView->height() < availableHeightBottom || availableHeightBottom > availableHeightTop )
233 y = mPosition.y() - mWebView->height();
235 mWebView->move( x, y );
241 if ( !mMapTipVisible )
247 if ( mDelayedClearTimer.isActive() || mWebView->underMouse() )
254 mDelayedClearTimer.start( msDelay );
257 mWebView->setHtml( QString() );
261 mMapTipVisible =
false;
293 if ( canvasFilter ==
"FALSE"_L1 )
303 QgsFeatureRequest request;
306 if ( !canvasFilter.isEmpty() )
311 if ( mapTip.isEmpty() )
313 exp.prepare( &context );
322 std::unique_ptr<QgsFeatureRenderer> renderer;
326 renderer->startRender( renderCtx, vlayer->
fields() );
329 const QString filterExpression = renderer->filter( vlayer->
fields() );
330 if ( !filterExpression.isEmpty() )
337 QgsFeatureIterator it = vlayer->
getFeatures( request );
342 context.setFeature( feature );
345 if ( filter && renderer && !renderer->willRenderFeature( feature, renderCtx ) )
350 if ( !mapTip.isEmpty() )
356 tipString = exp.evaluate( &context ).toString();
359 if ( !tipString.isEmpty() || timer.elapsed() >= 1000 )
367 renderer->stopRender( renderCtx );
375 QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer *>( layer );
404QString QgsMapTip::htmlText(
const QString &text,
int maxWidth )
406 const QgsSettings settings;
407 const QFont defaultFont = qApp->font();
408 const int fontSize = defaultFont.pointSize();
409 const QString fontFamily = defaultFont.family();
410 const QString backgroundColor = QgsApplication::palette().base().color().name();
411 const QString strokeColor = QgsApplication::palette().shadow().color().name();
412 const QString textColor = QgsApplication::palette().toolTipText().color().name();
413 return sMapTipTemplate.arg( fontSize ).arg( fontFamily ).arg( textColor ).arg( maxWidth == -1 ?
"" : QString::number( maxWidth ) ).arg( backgroundColor ).arg( strokeColor ).arg( text );
417void QgsMapTip::onLinkClicked(
const QUrl &url )
419 QDesktopServices::openUrl( url );
427 if ( !mapCanvas || !vlayer || !vlayer->
isSpatial() )
431 if ( mapTemplate.isEmpty() && displayExpression.isEmpty() )
453 if ( mapTemplate.isEmpty() )
457 tipText = exp.
evaluate( &context ).toString();
465 return QgsMapTip::htmlText( tipText, mapCanvas->width() / 2 );
471 if ( !mapCanvas || !rlayer || mapTemplate.isEmpty() )
488 return QgsMapTip::htmlText( tipText, mapCanvas->width() / 2 );
@ ExactIntersect
Use exact geometry intersection (slower) instead of bounding boxes.
static const double UI_SCALE_FACTOR
UI scaling factor.
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
static QgsExpressionContextScope * mapLayerPositionScope(const QgsPointXY &position)
Sets the expression context variables which are available for expressions triggered by moving the mou...
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Handles parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
static QString replaceExpressionText(const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...
QVariant evaluate()
Evaluate the feature and return the result.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
@ Filter
Features may be filtered, i.e. some features may not be rendered (categorized, rule based ....
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & combineFilterExpression(const QString &expression)
Modifies the existing filter expression to add an additional expression filter.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
static QString filterForLayer(QgsMapCanvas *canvas, QgsVectorLayer *layer)
Constructs a filter to use for selecting features from the given layer, in order to apply filters whi...
Map canvas is a class for displaying all GIS data types on a canvas.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
const QgsDateTimeRange & temporalRange() const
Returns map canvas datetime range.
QList< QgsMapLayer * > layers(bool expandGroupLayers=false) const
Returns the list of layers shown within the map canvas.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
virtual bool isVisibleInTemporalRange(const QgsDateTimeRange &range) const
Returns true if the layer should be visible and rendered for the specified time range.
Base class for all map layer types.
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
virtual Q_INVOKABLE QgsRectangle extent() const
Returns the extent of the layer.
virtual QgsMapLayerTemporalProperties * temporalProperties()
Returns the layer's temporal properties.
double scale() const
Returns the calculated map scale.
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer's CRS
void showMapTip(QgsMapLayer *thepLayer, QgsPointXY &mapPosition, const QPoint &pixelPosition, QgsMapCanvas *mpMapCanvas)
Show a maptip at a given point on the map canvas.
static QString rasterMapTipPreviewText(QgsMapLayer *layer, QgsMapCanvas *mapCanvas, const QString &mapTemplate)
Returns the html that would be displayed in a maptip for a given layer.
static QString vectorMapTipPreviewText(QgsMapLayer *layer, QgsMapCanvas *mapCanvas, const QString &mapTemplate, const QString &displayExpression)
Returns the html that would be displayed in a maptip for a given layer.
QgsMapTip()
Default constructor.
void clear(QgsMapCanvas *mpMapCanvas=nullptr, int msDelay=0)
Clear the current maptip if it exists.
Represents a raster layer.
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
void setYMinimum(double y)
Set the minimum y value.
void setXMinimum(double x)
Set the minimum x value.
void setYMaximum(double y)
Set the maximum y value.
void setXMaximum(double x)
Set the maximum x value.
QgsExpressionContext & expressionContext()
Gets the expression context.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
bool isTemporal() const
Returns true if the object's temporal range is enabled, and the object will be filtered when renderin...
Represents a vector layer which manages a vector based dataset.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
bool isSpatial() const final
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
QString displayExpression
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const final
Queries the layer for features specified in request.
A collection of stubs to mimic the API of QWebView on systems where the real library is not available...
#define QgsDebugMsgLevel(str, level)