QGIS API Documentation  2.7.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
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:212
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.
QPointF mOffsetFromReferencePoint
Describes the shift of the item content box to the reference point.
void writeXML(QDomDocument &doc) const
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
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
void readXML(const QDomDocument &doc, const QDomElement &itemElem)
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:104
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:95
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
void setMapPosition(const QgsPoint &pos)
Reimplemented from QgsAnnotationItem.
bool mMapPositionFixed
True: the item stays at the same map position, False: the item stays on same screen position...
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
void _writeXML(QDomDocument &doc, QDomElement &itemElem) const
static QgsNetworkAccessManager * instance()
returns a pointer to the single instance
void setHTMLPage(const QString &htmlFile)
QgsMapCanvas * mMapCanvas
pointer to map canvas
void drawFrame(QPainter *p)
qint64 QgsFeatureId
Definition: qgsfeature.h:30
double y() const
Definition: qgspoint.h:134
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)
void paint(QPainter *painter)
function to be implemented by derived classes
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...