QGIS API Documentation  2.8.2-Wien
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgscomposerobject.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposerobject.cpp
3  -------------------
4  begin : July 2014
5  copyright : (C) 2014 by Nyall Dawson,Radim Blazek
6  email : nyall dot dawson at gmail dot com
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 <QPainter>
19 
20 #include "qgscomposition.h"
21 #include "qgscomposerutils.h"
22 #include "qgscomposerobject.h"
23 #include "qgsdatadefined.h"
24 
25 #define FONT_WORKAROUND_SCALE 10 //scale factor for upscaling fontsize and downscaling painter
26 
27 #ifndef M_DEG2RAD
28 #define M_DEG2RAD 0.0174532925
29 #endif
30 
32  : QObject( 0 )
33  , mComposition( composition )
34 {
35 
36  // data defined strings
37  mDataDefinedNames.insert( QgsComposerObject::TestProperty, QString( "dataDefinedTestProperty" ) );
38 
39  if ( mComposition )
40  {
41  //connect to atlas toggling on/off and coverage layer and feature changes
42  //to update data defined values
43  connect( &mComposition->atlasComposition(), SIGNAL( toggled( bool ) ), this, SLOT( refreshDataDefinedProperty() ) );
44  connect( &mComposition->atlasComposition(), SIGNAL( coverageLayerChanged( QgsVectorLayer* ) ), this, SLOT( refreshDataDefinedProperty() ) );
45  connect( &mComposition->atlasComposition(), SIGNAL( featureChanged( QgsFeature* ) ), this, SLOT( refreshDataDefinedProperty() ) );
46  //also, refreshing composition triggers a recalculation of data defined properties
47  connect( mComposition, SIGNAL( refreshItemsTriggered() ), this, SLOT( refreshDataDefinedProperty() ) );
48 
49  //toggling atlas or changing coverage layer requires data defined expressions to be reprepared
50  connect( &mComposition->atlasComposition(), SIGNAL( toggled( bool ) ), this, SLOT( prepareDataDefinedExpressions() ) );
51  connect( &mComposition->atlasComposition(), SIGNAL( coverageLayerChanged( QgsVectorLayer* ) ), this, SLOT( prepareDataDefinedExpressions() ) );
52  }
53 
54 }
55 
57 {
58 
59 }
60 
61 bool QgsComposerObject::writeXML( QDomElement &elem, QDomDocument &doc ) const
62 {
63  if ( elem.isNull() )
64  {
65  return false;
66  }
67 
68  //data defined properties
69  QgsComposerUtils::writeDataDefinedPropertyMap( elem, doc, &mDataDefinedNames, &mDataDefinedProperties );
70 
71  return true;
72 }
73 
74 bool QgsComposerObject::readXML( const QDomElement &itemElem, const QDomDocument &doc )
75 {
76  Q_UNUSED( doc );
77  if ( itemElem.isNull() )
78  {
79  return false;
80  }
81 
82  //data defined properties
83  QgsComposerUtils::readDataDefinedPropertyMap( itemElem, &mDataDefinedNames, &mDataDefinedProperties );
84 
85  return true;
86 }
87 
89 {
90  if ( property == QgsComposerObject::AllProperties || property == QgsComposerObject::NoProperty )
91  {
92  //bad property requested, don't return anything
93  return 0;
94  }
95 
96  //find corresponding QgsDataDefined and return it
97  QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined* >::const_iterator it = mDataDefinedProperties.find( property );
98  if ( it != mDataDefinedProperties.constEnd() )
99  {
100  return it.value();
101  }
102 
103  //could not find matching QgsDataDefined
104  return 0;
105 }
106 
107 void QgsComposerObject::setDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property, const bool active, const bool useExpression, const QString &expression, const QString &field )
108 {
109  if ( property == QgsComposerObject::AllProperties || property == QgsComposerObject::NoProperty )
110  {
111  //bad property requested
112  return;
113  }
114 
115  bool defaultVals = ( !active && !useExpression && expression.isEmpty() && field.isEmpty() );
116 
117  if ( mDataDefinedProperties.contains( property ) )
118  {
119  QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined* >::const_iterator it = mDataDefinedProperties.find( property );
120  if ( it != mDataDefinedProperties.constEnd() )
121  {
122  QgsDataDefined* dd = it.value();
123  dd->setActive( active );
124  dd->setUseExpression( useExpression );
125  dd->setExpressionString( expression );
126  dd->setField( field );
127  }
128  }
129  else if ( !defaultVals )
130  {
131  QgsDataDefined* dd = new QgsDataDefined( active, useExpression, expression, field );
132  mDataDefinedProperties.insert( property, dd );
133  }
134 }
135 
137 {
138  //nothing to do in base class for now
139 }
140 
142 {
143  Q_UNUSED( property );
144 
145  //nothing to do in base class for now
146 }
147 
148 bool QgsComposerObject::dataDefinedEvaluate( const DataDefinedProperty property, QVariant &expressionValue )
149 {
150  if ( !mComposition )
151  {
152  return false;
153  }
154  return mComposition->dataDefinedEvaluate( property, expressionValue, &mDataDefinedProperties );
155 }
156 
157 void QgsComposerObject::prepareDataDefinedExpressions() const
158 {
159  //use atlas coverage layer if set
160  QgsVectorLayer* atlasLayer = 0;
161  if ( mComposition )
162  {
164  if ( atlas && atlas->enabled() )
165  {
166  atlasLayer = atlas->coverageLayer();
167  }
168  }
169 
170  //prepare all QgsDataDefineds
171  QMap< DataDefinedProperty, QgsDataDefined* >::const_iterator it = mDataDefinedProperties.constBegin();
172  if ( it != mDataDefinedProperties.constEnd() )
173  {
174  it.value()->prepareExpression( atlasLayer );
175  }
176 }