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