QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgshtmlannotationitem.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgshtmlannotationitem.h
3  ------------------------
4  begin : February 26, 2010
5  copyright : (C) 2010 by Marco Hugentobler
6  email : marco dot hugentobler at hugis dot net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgshtmlannotationitem.h"
19 #include "qgsattributeeditor.h"
20 #include "qgsfeature.h"
21 #include "qgslogger.h"
22 #include "qgsmapcanvas.h"
23 #include "qgsmaplayerregistry.h"
24 #include "qgsmaptool.h"
25 #include "qgsvectorlayer.h"
26 #include "qgsexpression.h"
28 
29 #include <QDomElement>
30 #include <QDir>
31 #include <QFile>
32 #include <QFileInfo>
33 #include <QGraphicsProxyWidget>
34 #include <QPainter>
35 #include <QSettings>
36 #include <QWidget>
37 
38 
39 QgsHtmlAnnotationItem::QgsHtmlAnnotationItem( QgsMapCanvas* canvas, QgsVectorLayer* vlayer, bool hasFeature, int feature )
40  : QgsAnnotationItem( canvas ), mWidgetContainer( 0 ), mWebView( 0 ), mVectorLayer( vlayer ),
41  mHasAssociatedFeature( hasFeature ), mFeatureId( feature )
42 {
43  mWebView = new QWebView();
44  mWebView->page()->setNetworkAccessManager( QgsNetworkAccessManager::instance() );
45 
46  mWidgetContainer = new QGraphicsProxyWidget( this );
47  mWidgetContainer->setWidget( mWebView );
48 
49  QObject::connect( mWebView->page()->mainFrame(), SIGNAL( javaScriptWindowObjectCleared() ), this, SLOT( javascript() ) );
50 
51  if ( mVectorLayer && mMapCanvas )
52  {
53  QObject::connect( mVectorLayer, SIGNAL( layerModified() ), this, SLOT( setFeatureForMapPosition() ) );
54  QObject::connect( mMapCanvas, SIGNAL( renderComplete( QPainter* ) ), this, SLOT( setFeatureForMapPosition() ) );
55  QObject::connect( mMapCanvas, SIGNAL( layersChanged() ), this, SLOT( updateVisibility() ) );
56  }
57 
58  setFeatureForMapPosition();
59 }
60 
62 {
63  delete mWebView;
64 }
65 
66 void QgsHtmlAnnotationItem::setHTMLPage( const QString& htmlFile )
67 {
68  QFile file( htmlFile );
69  mHtmlFile = htmlFile;
70  if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
71  {
72  mHtmlSource = "";
73  }
74  else
75  {
76  QTextStream in( &file );
77  in.setCodec( "UTF-8" );
78  mHtmlSource = in.readAll();
79  }
80 
81  file.close();
82  setFeatureForMapPosition();
83 }
84 
86 {
88  setFeatureForMapPosition();
89 }
90 
91 void QgsHtmlAnnotationItem::paint( QPainter * painter )
92 {
93  Q_UNUSED( painter );
94 }
95 
96 void QgsHtmlAnnotationItem::paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget )
97 {
98  Q_UNUSED( option );
99  Q_UNUSED( widget );
100  if ( !painter || !mWidgetContainer )
101  {
102  return;
103  }
104 
105  drawFrame( painter );
106  if ( mMapPositionFixed )
107  {
108  drawMarkerSymbol( painter );
109  }
110 
111  mWidgetContainer->setGeometry( QRectF( mOffsetFromReferencePoint.x() + mFrameBorderWidth / 2.0, mOffsetFromReferencePoint.y()
112  + mFrameBorderWidth / 2.0, mFrameSize.width() - mFrameBorderWidth, mFrameSize.height()
113  - mFrameBorderWidth ) );
114  if ( data( 1 ).toString() == "composer" )
115  {
116  mWidgetContainer->widget()->render( painter, mOffsetFromReferencePoint.toPoint() );
117  }
118 
119  if ( isSelected() )
120  {
121  drawSelectionBoxes( painter );
122  }
123 }
124 
126 {
127  if ( mWebView )
128  {
129  QSizeF widgetMinSize = mWebView->minimumSize();
130  return QSizeF( 2 * mFrameBorderWidth + widgetMinSize.width(), 2 * mFrameBorderWidth + widgetMinSize.height() );
131  }
132  else
133  {
134  return QSizeF( 0, 0 );
135  }
136 }
137 
138 void QgsHtmlAnnotationItem::writeXML( QDomDocument& doc ) const
139 {
140  QDomElement documentElem = doc.documentElement();
141  if ( documentElem.isNull() )
142  {
143  return;
144  }
145 
146  QDomElement formAnnotationElem = doc.createElement( "HtmlAnnotationItem" );
147  if ( mVectorLayer )
148  {
149  formAnnotationElem.setAttribute( "vectorLayer", mVectorLayer->id() );
150  }
151  formAnnotationElem.setAttribute( "hasFeature", mHasAssociatedFeature );
152  formAnnotationElem.setAttribute( "feature", mFeatureId );
153  formAnnotationElem.setAttribute( "htmlfile", htmlPage() );
154 
155  _writeXML( doc, formAnnotationElem );
156  documentElem.appendChild( formAnnotationElem );
157 }
158 
159 void QgsHtmlAnnotationItem::readXML( const QDomDocument& doc, const QDomElement& itemElem )
160 {
161  mVectorLayer = 0;
162  if ( itemElem.hasAttribute( "vectorLayer" ) )
163  {
164  mVectorLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( itemElem.attribute( "vectorLayer", "" ) ) );
165  if ( mVectorLayer )
166  {
167  QObject::connect( mVectorLayer, SIGNAL( layerModified() ), this, SLOT( setFeatureForMapPosition() ) );
168  QObject::connect( mMapCanvas, SIGNAL( renderComplete( QPainter* ) ), this, SLOT( setFeatureForMapPosition() ) );
169  QObject::connect( mMapCanvas, SIGNAL( layersChanged() ), this, SLOT( updateVisibility() ) );
170  }
171  }
172  mHasAssociatedFeature = itemElem.attribute( "hasFeature", "0" ).toInt();
173  mFeatureId = itemElem.attribute( "feature", "0" ).toInt();
174  mHtmlFile = itemElem.attribute( "htmlfile", "" );
175  QDomElement annotationElem = itemElem.firstChildElement( "AnnotationItem" );
176  if ( !annotationElem.isNull() )
177  {
178  _readXML( doc, annotationElem );
179  }
180 
181  if ( mWebView )
182  {
183  setHTMLPage( mHtmlFile );
184  }
185  updateVisibility();
186 }
187 
188 void QgsHtmlAnnotationItem::setFeatureForMapPosition()
189 {
190  if ( !mVectorLayer || !mMapCanvas )
191  {
192  return;
193  }
194 
195  QSettings settings;
196  double halfIdentifyWidth = QgsMapTool::searchRadiusMU( mMapCanvas );
197  QgsRectangle searchRect( mMapPosition.x() - halfIdentifyWidth, mMapPosition.y() - halfIdentifyWidth,
198  mMapPosition.x() + halfIdentifyWidth, mMapPosition.y() + halfIdentifyWidth );
199 
200  QgsFeatureIterator fit = mVectorLayer->getFeatures( QgsFeatureRequest().setFilterRect( searchRect ).setFlags( QgsFeatureRequest::NoGeometry | QgsFeatureRequest::ExactIntersect ) );
201 
202  QgsFeature currentFeature;
203  QgsFeatureId currentFeatureId = 0;
204  bool featureFound = false;
205 
206  while ( fit.nextFeature( currentFeature ) )
207  {
208  currentFeatureId = currentFeature.id();
209  featureFound = true;
210  break;
211  }
212 
213  mHasAssociatedFeature = featureFound;
214  mFeatureId = currentFeatureId;
215  mFeature = currentFeature;
216 
217  QString newtext = QgsExpression::replaceExpressionText( mHtmlSource, &mFeature, vectorLayer() );
218  mWebView->setHtml( newtext );
219 }
220 
221 void QgsHtmlAnnotationItem::updateVisibility()
222 {
223  bool visible = true;
224  if ( mVectorLayer && mMapCanvas )
225  {
226  visible = mMapCanvas->layers().contains( mVectorLayer );
227  }
228  setVisible( visible );
229 }
230 
231 void QgsHtmlAnnotationItem::javascript()
232 {
233  QWebFrame *frame = mWebView->page()->mainFrame();
234  frame->addToJavaScriptWindowObject( "canvas", mMapCanvas );
235  frame->addToJavaScriptWindowObject( "layer", mVectorLayer );
236 }
237 
238 
239 
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:100
void readXML(const QDomDocument &doc, const QDomElement &itemElem) override
Wrapper for iterator of features from vector data provider or vector layer.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
static double searchRadiusMU(const QgsRenderContext &context)
Get search radius in map units for given context.
Definition: qgsmaptool.cpp:213
QgsVectorLayer * vectorLayer() const
void _readXML(const QDomDocument &doc, const QDomElement &annotationElem)
double mFrameBorderWidth
Width of the frame.
Use exact geometry intersection (slower) instead of bounding boxes.
void setMapPosition(const QgsPoint &pos) override
Reimplemented from QgsAnnotationItem.
QPointF mOffsetFromReferencePoint
Describes the shift of the item content box to the reference point.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
static QgsNetworkAccessManager * instance()
Definition: qgssingleton.h:23
QList< QgsMapLayer * > layers() const
return list of layers within map canvas.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:105
QgsHtmlAnnotationItem(QgsMapCanvas *canvas, QgsVectorLayer *vlayer=0, bool hasFeature=false, int feature=0)
double x() const
Definition: qgspoint.h:126
void drawSelectionBoxes(QPainter *p)
virtual void setMapPosition(const QgsPoint &pos)
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
Definition: qgsmaplayer.cpp:98
void drawMarkerSymbol(QPainter *p)
A class to represent a point.
Definition: qgspoint.h:63
An annotation item can be either placed either on screen corrdinates or on map coordinates.
QString file
Definition: qgssvgcache.cpp:76
bool mMapPositionFixed
True: the item stays at the same map position, False: the item stays on same screen position...
void _writeXML(QDomDocument &doc, QDomElement &itemElem) const
void paint(QPainter *painter) override
function to be implemented by derived classes
void setHTMLPage(const QString &htmlFile)
QgsMapCanvas * mMapCanvas
pointer to map canvas
void drawFrame(QPainter *p)
void writeXML(QDomDocument &doc) const override
qint64 QgsFeatureId
Definition: qgsfeature.h:30
double y() const
Definition: qgspoint.h:134
QSizeF minimumFrameSize() const override
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Represents a vector layer which manages a vector based data sets.
QgsPoint mMapPosition
Map position (in case mMapPositionFixed is true)
QSizeF mFrameSize
Size of the frame (without balloon)
static QString replaceExpressionText(const QString &action, const QgsFeature *feat, QgsVectorLayer *layer, const QMap< QString, QVariant > *substitutionMap=0, const QgsDistanceArea *distanceArea=0)
This function currently replaces each expression between [% and %] in the string with the result of i...