QGIS API Documentation 3.27.0-Master (f261cc1f8b)
qgshtmlwidgetwrapper.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgshtmlwidgetwrapper.h
3
4 ---------------------
5 begin : 23.03.2019
6 copyright : (C) 2019 by Alessandro Pasotti
7 email : elpaso at itopen dot it
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
18#include "qgsmessagelog.h"
20#include "qgsapplication.h"
21#include "qgswebframe.h"
22#include <QScreen>
23
24QgsHtmlWidgetWrapper::QgsHtmlWidgetWrapper( QgsVectorLayer *layer, QWidget *editor, QWidget *parent )
25 : QgsWidgetWrapper( layer, editor, parent )
26{
27 connect( this, &QgsWidgetWrapper::contextChanged, this, &QgsHtmlWidgetWrapper::setHtmlContext );
28}
29
31{
32 return true;
33}
34
35QWidget *QgsHtmlWidgetWrapper::createWidget( QWidget *parent )
36{
37 return new QgsWebView( parent );
38}
39
40void QgsHtmlWidgetWrapper::initWidget( QWidget *editor )
41{
42 mWidget = qobject_cast<QgsWebView *>( editor );
43
44 if ( !mWidget )
45 return;
46
47 mWidget->setHtml( mHtmlCode );
48#ifdef WITH_QTWEBKIT
49
50 const int horizontalDpi = mWidget->logicalDpiX();
51
52 mWidget->setZoomFactor( horizontalDpi / 96.0 );
53
54 QWebPage *page = mWidget->page();
55 connect( page, &QWebPage::contentsChanged, this, &QgsHtmlWidgetWrapper::fixHeight, Qt::ConnectionType::UniqueConnection );
56 connect( page, &QWebPage::loadFinished, this, &QgsHtmlWidgetWrapper::fixHeight, Qt::ConnectionType::UniqueConnection );
57
58#endif
59
60 checkGeometryNeeds();
61}
62
64{
65 if ( !mWidget )
66 return;
67
68 initWidget( mWidget );
69}
70
71void QgsHtmlWidgetWrapper::checkGeometryNeeds()
72{
73 if ( !mWidget )
74 return;
75
76 // initialize a temporary QgsWebView to render HTML code and check if one evaluated expression
77 // needs geometry
78 QgsWebView webView;
79 NeedsGeometryEvaluator evaluator;
80
81 const QgsAttributeEditorContext attributecontext = context();
82 const QgsExpressionContext expressionContext = layer()->createExpressionContext();
83 evaluator.setExpressionContext( expressionContext );
84
85 auto frame = webView.page()->mainFrame();
86 connect( frame, &QWebFrame::javaScriptWindowObjectCleared, frame, [ frame, &evaluator ]
87 {
88 frame->addToJavaScriptWindowObject( QStringLiteral( "expression" ), &evaluator );
89 } );
90
91 webView.setHtml( mHtmlCode );
92
93 mNeedsGeometry = evaluator.needsGeometry();
94}
95
96void QgsHtmlWidgetWrapper::setHtmlCode( const QString &htmlCode )
97{
98 mHtmlCode = htmlCode;
99 checkGeometryNeeds();
100}
101
102void QgsHtmlWidgetWrapper::setHtmlContext( )
103{
104 if ( !mWidget )
105 return;
106
107 const QgsAttributeEditorContext attributecontext = context();
108 QgsExpressionContext expressionContext = layer()->createExpressionContext();
109 expressionContext << QgsExpressionContextUtils::formScope( mFeature, attributecontext.attributeFormModeString() );
110 if ( attributecontext.parentFormFeature().isValid() )
111 {
112 expressionContext << QgsExpressionContextUtils::parentFormScope( attributecontext.parentFormFeature() );
113 }
114 expressionContext.setFeature( mFeature );
115
116 HtmlExpression *htmlExpression = new HtmlExpression();
117 htmlExpression->setExpressionContext( expressionContext );
118 auto frame = mWidget->page()->mainFrame();
119 connect( frame, &QWebFrame::javaScriptWindowObjectCleared, frame, [ = ]
120 {
121 frame->addToJavaScriptWindowObject( QStringLiteral( "expression" ), htmlExpression );
122 } );
123
124 mWidget->setHtml( mHtmlCode );
125}
126
127#ifdef WITH_QTWEBKIT
128void QgsHtmlWidgetWrapper::fixHeight()
129{
130 QWebPage *page = mWidget->page();
131 const int docHeight { page->mainFrame()->contentsSize().height() };
132 mWidget->setFixedHeight( docHeight );
133}
134#endif
135
137{
138 if ( !mWidget )
139 return;
140
141 mFeature = feature;
142 setHtmlContext();
143}
144
146{
147 return mNeedsGeometry;
148}
149
150
152void HtmlExpression::setExpressionContext( const QgsExpressionContext &context )
153{
154 mExpressionContext = context;
155}
156
157QString HtmlExpression::evaluate( const QString &expression ) const
158{
159 QgsExpression exp = QgsExpression( expression );
160 exp.prepare( &mExpressionContext );
161 return exp.evaluate( &mExpressionContext ).toString();
162}
163
164void NeedsGeometryEvaluator::evaluate( const QString &expression )
165{
166 QgsExpression exp = QgsExpression( expression );
167 exp.prepare( &mExpressionContext );
168 mNeedsGeometry |= exp.needsGeometry();
169}
170
171void NeedsGeometryEvaluator::setExpressionContext( const QgsExpressionContext &context )
172{
173 mExpressionContext = context;
174}
175
176
The QWebPage class is a collection of stubs to mimic the API of a QWebPage on systems where QtWebkit ...
Definition: qgswebpage.h:104
This class contains context information for attribute editor widgets.
QString attributeFormModeString() const
Returns given attributeFormMode as string.
QgsFeature parentFormFeature() const
Returns the feature of the currently edited parent form in its actual state.
static QgsExpressionContextScope * parentFormScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current parent attribute form/tab...
static QgsExpressionContextScope * formScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current attribute form/table form...
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QVariant evaluate()
Evaluate the feature and return the result.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:216
void reinitWidget()
Clears the content and makes new initialization.
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
QgsHtmlWidgetWrapper(QgsVectorLayer *layer, QWidget *editor, QWidget *parent)
Create a html widget wrapper.
void setHtmlCode(const QString &htmlCode)
Sets the HTML code to htmlCode.
bool valid() const override
Returns true if the widget has been properly initialized.
void setFeature(const QgsFeature &feature) override
bool needsGeometry() const
Returns true if the widget needs feature geometry.
Represents a vector layer which manages a vector based data sets.
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
The QgsWebView class is a collection of stubs to mimic the API of QWebView on systems where the real ...
Definition: qgswebview.h:66
Manages an editor widget Widget and wrapper share the same parent.
void contextChanged()
Signal when QgsAttributeEditorContext mContext changed.
const QgsAttributeEditorContext & context() const
Returns information about the context in which this widget is shown.
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.