QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgsformannotationitem.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsformannotationitem.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 "qgsformannotationitem.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 <QDomElement>
27 #include <QDir>
28 #include <QFile>
29 #include <QFileInfo>
30 #include <QGraphicsProxyWidget>
31 #include <QPainter>
32 #include <QSettings>
33 #include <QUiLoader>
34 #include <QWidget>
35 
36 QgsFormAnnotationItem::QgsFormAnnotationItem( QgsMapCanvas* canvas, QgsVectorLayer* vlayer, bool hasFeature, int feature )
37  : QgsAnnotationItem( canvas ), mWidgetContainer( 0 ), mDesignerWidget( 0 ), mVectorLayer( vlayer ),
38  mHasAssociatedFeature( hasFeature ), mFeature( feature )
39 {
40  mWidgetContainer = new QGraphicsProxyWidget( this );
41  mWidgetContainer->setData( 0, "AnnotationItem" ); //mark embedded widget as belonging to an annotation item (composer knows it needs to be printed)
42  if ( mVectorLayer && mMapCanvas ) //default to the layers edit form
43  {
44  mDesignerForm = mVectorLayer->annotationForm();
45  QObject::connect( mVectorLayer, SIGNAL( layerModified() ), this, SLOT( setFeatureForMapPosition() ) );
46  QObject::connect( mMapCanvas, SIGNAL( renderComplete( QPainter* ) ), this, SLOT( setFeatureForMapPosition() ) );
47  QObject::connect( mMapCanvas, SIGNAL( layersChanged() ), this, SLOT( updateVisibility() ) );
48  }
49 
50  setFeatureForMapPosition();
51 }
52 
54 {
55  delete mDesignerWidget;
56 }
57 
58 void QgsFormAnnotationItem::setDesignerForm( const QString& uiFile )
59 {
60  mDesignerForm = uiFile;
61  mWidgetContainer->setWidget( 0 );
62  delete mDesignerWidget;
63  mDesignerWidget = createDesignerWidget( uiFile );
64  if ( mDesignerWidget )
65  {
66  mFrameBackgroundColor = mDesignerWidget->palette().color( QPalette::Window );
67  mWidgetContainer->setWidget( mDesignerWidget );
69  }
70 }
71 
72 QWidget* QgsFormAnnotationItem::createDesignerWidget( const QString& filePath )
73 {
74  QFile file( filePath );
75  if ( !file.open( QFile::ReadOnly ) )
76  {
77  return 0;
78  }
79 
80  QUiLoader loader;
81  QFileInfo fi( file );
82  loader.setWorkingDirectory( fi.dir() );
83  QWidget* widget = loader.load( &file, 0 );
84  file.close();
85 
86  //get feature and set attribute information
87  if ( mVectorLayer && mHasAssociatedFeature )
88  {
89  QgsFeature f;
90  if ( mVectorLayer->getFeatures( QgsFeatureRequest().setFilterFid( mFeature ).setFlags( QgsFeatureRequest::NoGeometry ) ).nextFeature( f ) )
91  {
92  const QgsFields& fields = mVectorLayer->pendingFields();
93  const QgsAttributes& attrs = f.attributes();
94  for ( int i = 0; i < attrs.count(); ++i )
95  {
96  if ( i < fields.count() )
97  {
98  QWidget* attWidget = widget->findChild<QWidget*>( fields[i].name() );
99  if ( attWidget )
100  {
101  QgsAttributeEditor::createAttributeEditor( widget, attWidget, mVectorLayer, i, attrs[i] );
102  }
103  }
104  }
105  }
106  }
107  return widget;
108 }
109 
111 {
113  setFeatureForMapPosition();
114 }
115 
116 void QgsFormAnnotationItem::paint( QPainter * painter )
117 {
118  Q_UNUSED( painter );
119 }
120 
121 void QgsFormAnnotationItem::paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget )
122 {
123  Q_UNUSED( option );
124  Q_UNUSED( widget );
125  if ( !painter || !mWidgetContainer )
126  {
127  return;
128  }
129 
130  drawFrame( painter );
131  if ( mMapPositionFixed )
132  {
133  drawMarkerSymbol( painter );
134  }
135 
136  mWidgetContainer->setGeometry( QRectF( mOffsetFromReferencePoint.x() + mFrameBorderWidth / 2.0, mOffsetFromReferencePoint.y()
137  + mFrameBorderWidth / 2.0, mFrameSize.width() - mFrameBorderWidth, mFrameSize.height()
138  - mFrameBorderWidth ) );
139 
140  if ( isSelected() )
141  {
142  drawSelectionBoxes( painter );
143  }
144 }
145 
147 {
148  if ( mDesignerWidget )
149  {
150  QSizeF widgetMinSize = mDesignerWidget->minimumSize();
151  return QSizeF( 2 * mFrameBorderWidth + widgetMinSize.width(), 2 * mFrameBorderWidth + widgetMinSize.height() );
152  }
153  else
154  {
155  return QSizeF( 0, 0 );
156  }
157 }
158 
160 {
161  if ( mDesignerWidget )
162  {
163  return mDesignerWidget->sizeHint();
164  }
165  else
166  {
167  return QSizeF( 0, 0 );
168  }
169 }
170 
171 void QgsFormAnnotationItem::writeXML( QDomDocument& doc ) const
172 {
173  QDomElement documentElem = doc.documentElement();
174  if ( documentElem.isNull() )
175  {
176  return;
177  }
178 
179  QDomElement formAnnotationElem = doc.createElement( "FormAnnotationItem" );
180  if ( mVectorLayer )
181  {
182  formAnnotationElem.setAttribute( "vectorLayer", mVectorLayer->id() );
183  }
184  formAnnotationElem.setAttribute( "hasFeature", mHasAssociatedFeature );
185  formAnnotationElem.setAttribute( "feature", mFeature );
186  formAnnotationElem.setAttribute( "designerForm", mDesignerForm );
187  _writeXML( doc, formAnnotationElem );
188  documentElem.appendChild( formAnnotationElem );
189 }
190 
191 void QgsFormAnnotationItem::readXML( const QDomDocument& doc, const QDomElement& itemElem )
192 {
193  mVectorLayer = 0;
194  if ( itemElem.hasAttribute( "vectorLayer" ) )
195  {
196  mVectorLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( itemElem.attribute( "vectorLayer", "" ) ) );
197  if ( mVectorLayer )
198  {
199  QObject::connect( mVectorLayer, SIGNAL( layerModified() ), this, SLOT( setFeatureForMapPosition() ) );
200  QObject::connect( mMapCanvas, SIGNAL( renderComplete( QPainter* ) ), this, SLOT( setFeatureForMapPosition() ) );
201  QObject::connect( mMapCanvas, SIGNAL( layersChanged() ), this, SLOT( updateVisibility() ) );
202  }
203  }
204  mHasAssociatedFeature = itemElem.attribute( "hasFeature", "0" ).toInt();
205  mFeature = itemElem.attribute( "feature", "0" ).toInt();
206  mDesignerForm = itemElem.attribute( "designerForm", "" );
207  QDomElement annotationElem = itemElem.firstChildElement( "AnnotationItem" );
208  if ( !annotationElem.isNull() )
209  {
210  _readXML( doc, annotationElem );
211  }
212 
213  mDesignerWidget = createDesignerWidget( mDesignerForm );
214  if ( mDesignerWidget )
215  {
216  mFrameBackgroundColor = mDesignerWidget->palette().color( QPalette::Window );
217  mWidgetContainer->setWidget( mDesignerWidget );
218  }
219  updateVisibility();
220 }
221 
222 void QgsFormAnnotationItem::setFeatureForMapPosition()
223 {
224  if ( !mVectorLayer || !mMapCanvas )
225  {
226  return;
227  }
228 
229  double halfIdentifyWidth = QgsMapTool::searchRadiusMU( mMapCanvas );
230  QgsRectangle searchRect( mMapPosition.x() - halfIdentifyWidth, mMapPosition.y() - halfIdentifyWidth,
231  mMapPosition.x() + halfIdentifyWidth, mMapPosition.y() + halfIdentifyWidth );
232 
233  QgsFeatureIterator fit = mVectorLayer->getFeatures( QgsFeatureRequest().setFilterRect( searchRect ).setFlags( QgsFeatureRequest::NoGeometry | QgsFeatureRequest::ExactIntersect ).setSubsetOfAttributes( QgsAttributeList() ) );
234 
235  QgsFeature currentFeature;
236  QgsFeatureId currentFeatureId = 0;
237  bool featureFound = false;
238 
239  while ( fit.nextFeature( currentFeature ) )
240  {
241  currentFeatureId = currentFeature.id();
242  featureFound = true;
243  break;
244  }
245 
246  mHasAssociatedFeature = featureFound;
247  mFeature = currentFeatureId;
248 
249  //create new embedded widget
250  mWidgetContainer->setWidget( 0 );
251  delete mDesignerWidget;
252  mDesignerWidget = createDesignerWidget( mDesignerForm );
253  if ( mDesignerWidget )
254  {
255  mFrameBackgroundColor = mDesignerWidget->palette().color( QPalette::Window );
256  mWidgetContainer->setWidget( mDesignerWidget );
257  }
258 }
259 
260 void QgsFormAnnotationItem::updateVisibility()
261 {
262  bool visible = true;
263  if ( mVectorLayer && mMapCanvas )
264  {
265  visible = mMapCanvas->layers().contains( mVectorLayer );
266  }
267  setVisible( visible );
268 }
269 
270 
271 
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:100
void paint(QPainter *painter)
function to be implemented by derived classes
Wrapper for iterator of features from vector data provider or vector layer.
QString annotationForm() const
get annotation form
A rectangle specified with double values.
Definition: qgsrectangle.h:35
QSizeF preferredFrameSize() const
Returns the optimal frame size.
static double searchRadiusMU(const QgsRenderContext &context)
Get search radius in map units for given context.
Definition: qgsmaptool.cpp:212
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.
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.
Container of fields for a vector layer.
Definition: qgsfield.h:172
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
QgsFormAnnotationItem(QgsMapCanvas *canvas, QgsVectorLayer *vlayer=0, bool hasFeature=false, int feature=0)
void setDesignerForm(const QString &uiFile)
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:104
double x() const
Definition: qgspoint.h:126
void drawSelectionBoxes(QPainter *p)
virtual void setMapPosition(const QgsPoint &pos)
void setMapPosition(const QgsPoint &pos)
Reimplemented from QgsAnnotationItem.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< int > QgsAttributeList
const QgsAttributes & attributes() const
Definition: qgsfeature.h:142
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)
int count() const
Return number of items.
Definition: qgsfield.h:214
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...
static Q_DECL_DEPRECATED QWidget * createAttributeEditor(QWidget *parent, QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value, QMap< int, QWidget * > &proxyWidgets)
Creates or prepares a attribute editor widget.
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
void _writeXML(QDomDocument &doc, QDomElement &itemElem) const
QVector< QVariant > QgsAttributes
Definition: qgsfeature.h:100
QgsMapCanvas * mMapCanvas
pointer to map canvas
void setFrameSize(const QSizeF &size)
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.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
void readXML(const QDomDocument &doc, const QDomElement &itemElem)
bool nextFeature(QgsFeature &f)
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 writeXML(QDomDocument &doc) const