Skip to content

Commit

Permalink
Raster maptips and html map functions
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso committed Nov 9, 2022
1 parent f040c26 commit 71c513a
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 47 deletions.
15 changes: 15 additions & 0 deletions resources/function_help/json/map_to_html_dl
@@ -0,0 +1,15 @@
{
"name": "map_to_html_dl",
"type": "function",
"groups": ["Maps"],
"description": "Merge map elements into a HTML definition list string.",
"arguments": [{
"arg": "map",
"description": "the input map"
}],
"examples": [{
"expression": "map_to_html_dl(map('qgis','rocks'))",
"returns": "<dl><dt>qgis</dt><dd>rocks</dd></dl>"
}],
"tags": ["formatted", "map", "html"]
}
15 changes: 15 additions & 0 deletions resources/function_help/json/map_to_html_table
@@ -0,0 +1,15 @@
{
"name": "map_to_html_table",
"type": "function",
"groups": ["Maps"],
"description": "Merge map elements into a HTML table string.",
"arguments": [{
"arg": "map",
"description": "the input map"
}],
"examples": [{
"expression": "map_to_html_table(map('qgis','rocks'))",
"returns": "<table><thead><th>qgis</th></thead><tbody><tr><td>rocks</td></tr></tbody></table>"
}],
"tags": ["formatted", "map", "html"]
}
78 changes: 77 additions & 1 deletion src/core/expression/qgsexpressionfunction.cpp
Expand Up @@ -1725,7 +1725,7 @@ static QVariant fcnRasterAttributes( const QVariantList &values, const QgsExpres
return QVariant();
}

const QVariantList data { layer->dataProvider()->attributeTable( bandNb )->row( value ) };
const QVariantList data = layer->dataProvider()->attributeTable( bandNb )->row( value );
if ( data.isEmpty() )
{
return QVariant();
Expand Down Expand Up @@ -1778,6 +1778,78 @@ static QVariant fcnAttribute( const QVariantList &values, const QgsExpressionCon
return feature.attribute( attr );
}

static QVariant fcnMapToHtmlTable( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
QString table { R"html(
<table>
<thead>
<th>%1</th>
</thead>
<tbody>
<tr><td>%2</td></tr>
</tbody>
</table>)html" };
QVariantMap dict;
if ( values.size() == 1 )
{
dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
}
else
{
parent->setEvalErrorString( QObject::tr( "Function `map_to_html_table` requires one parameter. %n given.", nullptr, values.length() ) );
return QVariant();
}

if ( dict.isEmpty() )
{
return QVariant();
}

QStringList headers;
QStringList cells;

for ( auto it = dict.cbegin(); it != dict.cend(); ++it )
{
headers.push_back( it.key() );
cells.push_back( it.value().toString( ) );
}

return table.arg( headers.join( QStringLiteral( "</th><th>" ) ), cells.join( QStringLiteral( "</td><td>" ) ) );
}

static QVariant fcnMapToHtmlDefinitionList( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
QString table { R"html(
<dl>
%1
</dl>)html" };
QVariantMap dict;
if ( values.size() == 1 )
{
dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
}
else
{
parent->setEvalErrorString( QObject::tr( "Function `map_to_html_dl` requires one parameter. %n given.", nullptr, values.length() ) );
return QVariant();
}

if ( dict.isEmpty() )
{
return QVariant();
}

QString rows;

for ( auto it = dict.cbegin(); it != dict.cend(); ++it )
{
rows.append( QStringLiteral( "<dt>%1</dt><dd>%2</dd>" ).arg( it.key(), it.value().toString() ) );
}

return table.arg( rows );
}


static QVariant fcnAttributes( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
QgsFeature feature;
Expand Down Expand Up @@ -8575,6 +8647,10 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< new QgsStaticExpressionFunction( QStringLiteral( "map_prefix_keys" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "map" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "prefix" ) ),
fcnMapPrefixKeys, QStringLiteral( "Maps" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "map_to_html_table" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "map" ) ),
fcnMapToHtmlTable, QStringLiteral( "Maps" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "map_to_html_dl" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "map" ) ),
fcnMapToHtmlDefinitionList, QStringLiteral( "Maps" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "url_encode" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "map" ) ),
fcnToFormUrlEncode, QStringLiteral( "Maps" ) )

Expand Down
99 changes: 53 additions & 46 deletions src/gui/qgsmaptip.cpp
Expand Up @@ -82,51 +82,53 @@ void QgsMapTip::showMapTip( QgsMapLayer *pLayer,
QString tipText, lastTipText, tipHtml, bodyStyle, containerStyle,
backgroundColor, strokeColor, textColor;

delete mWidget;
mWidget = new QWidget( pMapCanvas );
mWidget->setContentsMargins( MARGIN_VALUE, MARGIN_VALUE, MARGIN_VALUE, MARGIN_VALUE );
mWebView = new QgsWebView( mWidget );
if ( ! mWidget )
{
mWidget = new QWidget( pMapCanvas );
mWidget->setContentsMargins( MARGIN_VALUE, MARGIN_VALUE, MARGIN_VALUE, MARGIN_VALUE );
mWebView = new QgsWebView( mWidget );


#if WITH_QTWEBKIT
mWebView->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );//Handle link clicks by yourself
mWebView->setContextMenuPolicy( Qt::NoContextMenu ); //No context menu is allowed if you don't need it
connect( mWebView, &QWebView::linkClicked, this, &QgsMapTip::onLinkClicked );
connect( mWebView, &QWebView::loadFinished, this, [ = ]( bool ) { resizeContent(); } );
mWebView->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );//Handle link clicks by yourself
mWebView->setContextMenuPolicy( Qt::NoContextMenu ); //No context menu is allowed if you don't need it
connect( mWebView, &QWebView::linkClicked, this, &QgsMapTip::onLinkClicked );
connect( mWebView, &QWebView::loadFinished, this, [ = ]( bool ) { resizeContent(); } );
#endif

mWebView->page()->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
mWebView->page()->settings()->setAttribute( QWebSettings::JavascriptEnabled, true );
mWebView->page()->settings()->setAttribute( QWebSettings::LocalStorageEnabled, true );

// Disable scrollbars, avoid random resizing issues
mWebView->page()->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
mWebView->page()->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );

QHBoxLayout *layout = new QHBoxLayout;
layout->setContentsMargins( 0, 0, 0, 0 );
layout->addWidget( mWebView );

mWidget->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
mWidget->setLayout( layout );

// Assure the map tip is never larger than half the map canvas
const int MAX_WIDTH = pMapCanvas->geometry().width() / 2;
const int MAX_HEIGHT = pMapCanvas->geometry().height() / 2;
mWidget->setMaximumSize( MAX_WIDTH, MAX_HEIGHT );

// Start with 0 size,
// The content will automatically make it grow up to MaximumSize
mWidget->resize( 0, 0 );

backgroundColor = mWidget->palette().base().color().name();
strokeColor = mWidget->palette().shadow().color().name();
textColor = mWidget->palette().text().color().name();
mWidget->setStyleSheet( QString(
".QWidget{"
"border: 1px solid %1;"
"background-color: %2;}" ).arg(
strokeColor, backgroundColor ) );
mWebView->page()->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
mWebView->page()->settings()->setAttribute( QWebSettings::JavascriptEnabled, true );
mWebView->page()->settings()->setAttribute( QWebSettings::LocalStorageEnabled, true );

// Disable scrollbars, avoid random resizing issues
mWebView->page()->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
mWebView->page()->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );

QHBoxLayout *layout = new QHBoxLayout;
layout->setContentsMargins( 0, 0, 0, 0 );
layout->addWidget( mWebView );

mWidget->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
mWidget->setLayout( layout );

// Assure the map tip is never larger than half the map canvas
const int MAX_WIDTH = pMapCanvas->geometry().width() / 2;
const int MAX_HEIGHT = pMapCanvas->geometry().height() / 2;
mWidget->setMaximumSize( MAX_WIDTH, MAX_HEIGHT );

// Start with 0 size,
// The content will automatically make it grow up to MaximumSize
mWidget->resize( 0, 0 );

backgroundColor = mWidget->palette().base().color().name();
strokeColor = mWidget->palette().shadow().color().name();
textColor = mWidget->palette().text().color().name();
mWidget->setStyleSheet( QString(
".QWidget{"
"border: 1px solid %1;"
"background-color: %2;}" ).arg(
strokeColor, backgroundColor ) );
}

// Only supported layer types here:
switch ( pLayer->type() )
Expand Down Expand Up @@ -184,11 +186,11 @@ void QgsMapTip::showMapTip( QgsMapLayer *pLayer,
}

mWidget->move( pixelPosition.x() + cursorOffset, pixelPosition.y() );

mWebView->setHtml( tipHtml );
lastTipText = tipText;

mWidget->show();

}

void QgsMapTip::resizeContent()
Expand Down Expand Up @@ -343,12 +345,17 @@ QString QgsMapTip::fetchRaster( QgsMapLayer *layer, QgsPointXY &mapPosition, Qgs
return QString( );
}

QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( layer ) );
context.appendScope( QgsExpressionContextUtils::mapSettingsScope( mapCanvas->mapSettings() ) );
context.appendScope( QgsExpressionContextUtils::mapLayerPositionScope( mappedPosition ) );
QString tipText { rlayer->mapTipTemplate() };

if ( ! tipText.isEmpty() )
{
QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( layer ) );
context.appendScope( QgsExpressionContextUtils::mapSettingsScope( mapCanvas->mapSettings() ) );
context.appendScope( QgsExpressionContextUtils::mapLayerPositionScope( mappedPosition ) );
tipText = QgsExpression::replaceExpressionText( tipText, &context );
}

const QString mapTip = rlayer->mapTipTemplate();
return mapTip;
return tipText;
}

void QgsMapTip::applyFontSettings()
Expand Down

0 comments on commit 71c513a

Please sign in to comment.