QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgsformannotation.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsformannotation.cpp
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 "qgsformannotation.h"
21 #include "qgseditorwidgetwrapper.h"
22 #include "qgsfeature.h"
23 #include "qgsfeatureiterator.h"
24 #include "qgslogger.h"
25 #include "qgsmapcanvas.h"
26 #include "qgsproject.h"
27 #include "qgsmaptool.h"
28 #include "qgsvectorlayer.h"
29 #include "qgsgui.h"
30 #include <QDomElement>
31 #include <QDir>
32 #include <QFile>
33 #include <QFileInfo>
34 #include <QGraphicsProxyWidget>
35 #include <QPainter>
36 #include <QSettings>
37 #include <QUiLoader>
38 #include <QWidget>
39 
41  : QgsAnnotation( parent )
42 {}
43 
45 {
46  std::unique_ptr< QgsFormAnnotation > c( new QgsFormAnnotation() );
47  copyCommonProperties( c.get() );
48  c->setDesignerForm( mDesignerForm );
49  return c.release();
50 }
51 
52 void QgsFormAnnotation::setDesignerForm( const QString &uiFile )
53 {
54  mDesignerForm = uiFile;
55  mDesignerWidget.reset( createDesignerWidget( uiFile ) );
56  if ( mDesignerWidget )
57  {
58  mMinimumSize = mDesignerWidget->minimumSize();
59  if ( fillSymbol() )
60  {
61  QgsFillSymbol *newFill = fillSymbol()->clone();
62  newFill->setColor( mDesignerWidget->palette().color( QPalette::Window ) );
63  setFillSymbol( newFill );
64  }
65  // convert from size in pixels at 96 dpi to mm
66  setFrameSizeMm( preferredFrameSize() / 3.7795275 );
67  }
68  emit appearanceChanged();
69 }
70 
71 QWidget *QgsFormAnnotation::createDesignerWidget( const QString &filePath )
72 {
73  QFile file( filePath );
74  if ( !file.open( QFile::ReadOnly ) )
75  {
76  return nullptr;
77  }
78 
79  QUiLoader loader;
80  QFileInfo fi( file );
81  loader.setWorkingDirectory( fi.dir() );
82  QWidget *widget = loader.load( &file, nullptr );
83  file.close();
84 
85  //get feature and set attribute information
87  QgsVectorLayer *vectorLayer = qobject_cast< QgsVectorLayer * >( mapLayer() );
88  if ( vectorLayer && associatedFeature().isValid() )
89  {
90  QgsFields fields = vectorLayer->fields();
92  for ( int i = 0; i < attrs.count(); ++i )
93  {
94  if ( i < fields.count() )
95  {
96  QWidget *attWidget = widget->findChild<QWidget *>( fields.at( i ).name() );
97  if ( attWidget )
98  {
99  QgsEditorWidgetWrapper *eww = QgsGui::editorWidgetRegistry()->create( vectorLayer, i, attWidget, widget, context );
100  if ( eww )
101  {
102  eww->setValue( attrs.at( i ) );
103  }
104  }
105  }
106  }
107  }
108  return widget;
109 }
110 
111 void QgsFormAnnotation::renderAnnotation( QgsRenderContext &context, QSizeF size ) const
112 {
113  if ( !mDesignerWidget )
114  return;
115 
116  // scale painter back to 96 dpi, so that forms look good even in layout prints
117  context.painter()->save();
118  const double scaleFactor = context.painter()->device()->logicalDpiX() / 96.0;
119  context.painter()->scale( scaleFactor, scaleFactor );
120  size /= scaleFactor;
121 
122  mDesignerWidget->setFixedSize( size.toSize() );
123  context.painter()->setBrush( Qt::NoBrush );
124  context.painter()->setPen( Qt::NoPen );
125  mDesignerWidget->render( context.painter(), QPoint( 0, 0 ) );
126 
127  context.painter()->restore();
128 }
129 
131 {
132  if ( mDesignerWidget )
133  {
134  QSizeF widgetMinSize = mMinimumSize;
135  return QSizeF( contentsMargin().left() + contentsMargin().right() + widgetMinSize.width(),
136  contentsMargin().top() + contentsMargin().bottom() + widgetMinSize.height() );
137  }
138  else
139  {
140  return QSizeF( 0, 0 );
141  }
142 }
143 
145 {
146  if ( mDesignerWidget )
147  {
148  return mDesignerWidget->sizeHint();
149  }
150  else
151  {
152  return QSizeF( 0, 0 );
153  }
154 }
155 
156 void QgsFormAnnotation::writeXml( QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context ) const
157 {
158  QDomElement formAnnotationElem = doc.createElement( QStringLiteral( "FormAnnotationItem" ) );
159  formAnnotationElem.setAttribute( QStringLiteral( "designerForm" ), mDesignerForm );
160  _writeXml( formAnnotationElem, doc, context );
161  elem.appendChild( formAnnotationElem );
162 }
163 
164 void QgsFormAnnotation::readXml( const QDomElement &itemElem, const QgsReadWriteContext &context )
165 {
166  mDesignerForm = itemElem.attribute( QStringLiteral( "designerForm" ), QString() );
167  QDomElement annotationElem = itemElem.firstChildElement( QStringLiteral( "AnnotationItem" ) );
168  if ( !annotationElem.isNull() )
169  {
170  _readXml( annotationElem, context );
171  }
172  // upgrade old layer
173  if ( !mapLayer() && itemElem.hasAttribute( QStringLiteral( "vectorLayer" ) ) )
174  {
175  setMapLayer( QgsProject::instance()->mapLayer( itemElem.attribute( QStringLiteral( "vectorLayer" ) ) ) );
176  }
177 
178  mDesignerWidget.reset( createDesignerWidget( mDesignerForm ) );
179  if ( mDesignerWidget && fillSymbol() )
180  {
181  QgsFillSymbol *newFill = fillSymbol()->clone();
182  newFill->setColor( mDesignerWidget->palette().color( QPalette::Window ) );
183  setFillSymbol( newFill );
184  }
185 }
186 
188 {
190 
191  //create new embedded widget
192  mDesignerWidget.reset( createDesignerWidget( mDesignerForm ) );
193  if ( mDesignerWidget && fillSymbol() )
194  {
195  QgsFillSymbol *newFill = fillSymbol()->clone();
196  newFill->setColor( mDesignerWidget->palette().color( QPalette::Window ) );
197  setFillSymbol( newFill );
198  }
199  emit appearanceChanged();
200 }
201 
202 
203 
void writeXml(QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context) const override
Writes the annotation state to a DOM element.
QgsFillSymbol * fillSymbol() const
Returns the symbol that is used for rendering the annotation frame.
The class is used as a container of context for various read/write operations on other objects...
void appearanceChanged()
Emitted whenever the annotation&#39;s appearance changes.
QgsFeature associatedFeature() const
Returns the feature associated with the annotation, or an invalid feature if none has been set...
QSizeF preferredFrameSize() const
Returns the optimal frame size.
void setDesignerForm(const QString &uiFile)
Sets the path to the Qt Designer UI file to show in the annotation.
QString name
Definition: qgsfield.h:57
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:183
void setMapLayer(QgsMapLayer *layer)
Sets the map layer associated with the annotation.
QgsFormAnnotation * clone() const override
Clones the annotation, returning a new copy of the annotation reflecting the annotation&#39;s current sta...
QSizeF minimumFrameSize() const override
Returns the minimum frame size for the annotation.
This class contains context information for attribute editor widgets.
Manages an editor widget Widget and wrapper share the same parent.
void readXml(const QDomElement &itemElem, const QgsReadWriteContext &context) override
Restores the annotation&#39;s state from a DOM element.
Container of fields for a vector layer.
Definition: qgsfields.h:42
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
void _writeXml(QDomElement &itemElem, QDomDocument &doc, const QgsReadWriteContext &context) const
Writes common annotation properties to a DOM element.
Abstract base class for annotation items which are drawn over a map.
Definition: qgsannotation.h:48
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QgsFillSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1952
void setAssociatedFeature(const QgsFeature &feature) override
Sets the feature associated with the annotation.
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories...
Definition: qgsgui.cpp:58
QgsFormAnnotation(QObject *parent=nullptr)
Constructor for QgsFormAnnotation.
void copyCommonProperties(QgsAnnotation *target) const
Copies common annotation properties to the targe annotation.
virtual void setValue(const QVariant &value)=0
Is called, when the value of the widget needs to be changed.
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
void setFrameSizeMm(QSizeF size)
Sets the size (in millimeters) of the annotation&#39;s frame (the main area in which the annotation&#39;s con...
void _readXml(const QDomElement &annotationElem, const QgsReadWriteContext &context)
Reads common annotation properties from a DOM element.
QgsEditorWidgetWrapper * create(const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext &context=QgsAttributeEditorContext())
Create an attribute editor widget wrapper of a given type for a given field.
Contains information about the context of a rendering operation.
double bottom() const
Returns the bottom margin.
Definition: qgsmargins.h:90
QPainter * painter()
Returns the destination QPainter for the render operation.
double top() const
Returns the top margin.
Definition: qgsmargins.h:78
void renderAnnotation(QgsRenderContext &context, QSizeF size) const override
Renders the annotation&#39;s contents to a target /a context at the specified /a size.
QgsMargins contentsMargin() const
Returns the margins (in millimeters) between the outside of the frame and the annotation content...
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:411
QgsMapLayer * mapLayer() const
Returns the map layer associated with the annotation.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgssymbol.h:1003
void setFillSymbol(QgsFillSymbol *symbol)
Sets the fill symbol used for rendering the annotation frame.
A vector of attributes.
Definition: qgsattributes.h:57
Represents a vector layer which manages a vector based data sets.
virtual void setAssociatedFeature(const QgsFeature &feature)
Sets the feature associated with the annotation.
An annotation item that embeds a designer form showing the feature attribute.
QgsAttributes attributes
Definition: qgsfeature.h:65
void setColor(const QColor &color)
Sets the color for the symbol.
Definition: qgssymbol.cpp:450