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