Add map tip preview in raster layers properties

This commit is contained in:
Yoann Quenach de Quivillic 2023-03-28 15:49:20 +02:00
parent 7d1cc053d0
commit 0e61eb8e58
4 changed files with 156 additions and 26 deletions

View File

@ -46,6 +46,9 @@ Adds a properties page factory to the raster layer properties dialog.
virtual QgsExpressionContext createExpressionContext() const;
virtual bool eventFilter( QObject *obj, QEvent *ev );
protected slots:
};

View File

@ -63,6 +63,11 @@
#include "qgsrasterattributetablewidget.h"
#include "qgsrasterlayertemporalpropertieswidget.h"
#include "qgsexpressioncontextutils.h"
#include "qgsmaptip.h"
#include "qgswebframe.h"
#if WITH_QTWEBKIT
#include <QWebElement>
#endif
#include <QDesktopServices>
#include <QTableWidgetItem>
@ -222,7 +227,7 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer *lyr, QgsMapCanv
mRasterTransparencyWidget->pbnDefaultValues->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionOpenTable.svg" ) ) );
mRasterTransparencyWidget->pbnImportTransparentPixelValues->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileOpen.svg" ) ) );
mRasterTransparencyWidget->pbnExportTransparentPixelValues->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileSave.svg" ) ) );
initMapTipPreview();
if ( !mRasterLayer )
{
@ -1921,3 +1926,89 @@ void QgsRasterLayerProperties::updateGammaSlider( double value )
{
whileBlocking( mSliderGamma )->setValue( value * 100 );
}
bool QgsRasterLayerProperties::eventFilter( QObject *obj, QEvent *ev )
{
// If the map tip preview container is resized, resize the map tip
if ( obj == mMapTipPreviewContainer && ev->type() == QEvent::Resize )
{
resizeMapTip();
}
return QgsOptionsDialogBase::eventFilter( obj, ev );
}
void QgsRasterLayerProperties::initMapTipPreview()
{
// HTML editor and preview are in a splitter. By default, the editor takes 2/3 of the space
mMapTipSplitter->setSizes( { 400, 200 } );
// Event filter is used to resize the map tip when the container is resized
mMapTipPreviewContainer->installEventFilter( this );
// Note: there's quite a bit of overlap between this and the code in QgsMapTip::showMapTip
// Create and style the map tip frame
mMapTipPreviewWidget = new QWidget( mMapTipPreviewContainer );
mMapTipPreviewWidget->setContentsMargins( MARGIN_VALUE, MARGIN_VALUE, MARGIN_VALUE, MARGIN_VALUE );
const QString backgroundColor = mMapTipPreviewWidget->palette().base().color().name();
const QString strokeColor = mMapTipPreviewWidget->palette().shadow().color().name();
mMapTipPreviewWidget->setStyleSheet( QString(
".QWidget{"
"border: 1px solid %1;"
"background-color: %2;}" ).arg(
strokeColor, backgroundColor ) );
// Create the WebView
mMapTipPreview = new QgsWebView( mMapTipPreviewWidget );
#if WITH_QTWEBKIT
mMapTipPreview->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );//Handle link clicks by yourself
mMapTipPreview->setContextMenuPolicy( Qt::NoContextMenu ); //No context menu is allowed if you don't need it
connect( mMapTipPreview, &QWebView::loadFinished, this, &QgsRasterLayerProperties::resizeMapTip );
#endif
mMapTipPreview->page()->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
mMapTipPreview->page()->settings()->setAttribute( QWebSettings::JavascriptEnabled, true );
mMapTipPreview->page()->settings()->setAttribute( QWebSettings::LocalStorageEnabled, true );
// Disable scrollbars, avoid random resizing issues
mMapTipPreview->page()->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
mMapTipPreview->page()->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );
QHBoxLayout *hlayout = new QHBoxLayout;
hlayout->setContentsMargins( 0, 0, 0, 0 );
hlayout->addWidget( mMapTipPreview );
mMapTipPreviewWidget->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
mMapTipPreviewWidget->setLayout( hlayout );
// Update the map tip preview when the expression or the map tip template changes
connect( mMapTipWidget, &QgsCodeEditorHTML::textChanged, this, &QgsRasterLayerProperties::updateMapTipPreview );
}
void QgsRasterLayerProperties::updateMapTipPreview()
{
mMapTipPreviewWidget->setMaximumSize( mMapTipPreviewContainer->width(), mMapTipPreviewContainer->height() );
const QString htmlContent = QgsMapTip::rasterMapTipPreviewText( mRasterLayer, mMapCanvas, mMapTipWidget->text() );
mMapTipPreview->setHtml( htmlContent );
}
void QgsRasterLayerProperties::resizeMapTip()
{
// Ensure the map tip is not bigger than the container
mMapTipPreviewWidget->setMaximumSize( mMapTipPreviewContainer->width(), mMapTipPreviewContainer->height() );
#if WITH_QTWEBKIT
// Get the content size
const QWebElement container = mMapTipPreview->page()->mainFrame()->findFirstElement(
QStringLiteral( "#QgsWebViewContainer" ) );
const int width = container.geometry().width() + MARGIN_VALUE * 2;
const int height = container.geometry().height() + MARGIN_VALUE * 2;
mMapTipPreviewWidget->resize( width, height );
// Move the map tip to the center of the container
mMapTipPreviewWidget->move( ( mMapTipPreviewContainer->width() - mMapTipPreviewWidget->width() ) / 2,
( mMapTipPreviewContainer->height() - mMapTipPreviewWidget->height() ) / 2 );
#else
mMapTipPreview->adjustSize();
#endif
}

View File

@ -48,6 +48,7 @@ class QgsMapLayerConfigWidget;
class QgsPropertyOverrideButton;
class QgsRasterTransparencyWidget;
class QgsRasterAttributeTableWidget;
class QgsWebView;
/**
@ -92,6 +93,8 @@ class GUI_EXPORT QgsRasterLayerProperties : public QgsOptionsDialogBase, private
QgsExpressionContext createExpressionContext() const override;
bool eventFilter( QObject *obj, QEvent *ev ) override;
protected slots:
//! \brief auto slot executed when the active page in the main widget stack is changed
void optionsStackedWidget_CurrentChanged( int index ) override SIP_SKIP ;
@ -199,6 +202,11 @@ class GUI_EXPORT QgsRasterLayerProperties : public QgsOptionsDialogBase, private
void urlClicked( const QUrl &url );
// Update the preview of the map tip
void updateMapTipPreview();
// Resize the map tip preview
void resizeMapTip();
private:
QPushButton *mBtnStyle = nullptr;
QPushButton *mBtnMetadata = nullptr;
@ -305,5 +313,11 @@ class GUI_EXPORT QgsRasterLayerProperties : public QgsOptionsDialogBase, private
QgsCoordinateReferenceSystem mBackupCrs;
QgsRasterAttributeTableWidget *mRasterAttributeTableWidget = nullptr;
void initMapTipPreview();
QWidget *mMapTipPreviewWidget = nullptr;
QgsWebView *mMapTipPreview = nullptr;
const int MARGIN_VALUE = 5;
};
#endif

View File

@ -1487,8 +1487,46 @@ p, li { white-space: pre-wrap; }
<property name="title">
<string>HTML Map Tip</string>
</property>
<layout class="QGridLayout" name="gridLayout_81">
<item row="1" column="2">
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="0" colspan="2">
<widget class="QSplitter" name="mMapTipSplitter">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QgsCodeEditorHTML" name="mMapTipWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
</widget>
<widget class="QGroupBox" name="mMapTipPreviewContainer">
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="title">
<string>Preview</string>
</property>
</widget>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="mInsertExpressionButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@ -1504,23 +1542,17 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QgsCodeEditorHTML" name="mMapTipWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="labelMapTipInfo">
<property name="text">
<string>The HTML map tips are shown when moving mouse over features of the currently selected layer when the 'Show Map Tips' action is toggled on. If no HTML code is set, the feature display name is used.</string>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<item row="1" column="0">
<widget class="QgsExpressionLineEdit" name="mMapTipExpressionWidget" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
@ -1530,16 +1562,6 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QLabel" name="labelMapTipInfo">
<property name="text">
<string>The HTML map tips are shown when moving mouse over features of the currently selected layer when the 'Show Map Tips' action is toggled on.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>