QGIS API Documentation  2.99.0-Master (e077efd)
qgscomposeritemgroup.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposeritemgroup.cpp
3  ------------------------
4  begin : 2nd June 2008
5  copyright : (C) 2008 by Marco Hugentobler
6  email : marco dot hugentobler at karto dot baug dot ethz dot ch
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 "qgscomposeritemgroup.h"
19 #include "qgscomposition.h"
20 #include "qgscomposerutils.h"
21 #include "qgslogger.h"
22 #include "qgscomposermodel.h"
23 
24 #include <QPen>
25 #include <QPainter>
26 
28  : QgsComposerItem( c )
29 {
30  setZValue( 90 );
31  show();
32 }
33 
35 {
36  //loop through group members and remove them from the scene
37  Q_FOREACH ( QgsComposerItem* item, mItems )
38  {
39  if ( !item || item->isRemoved() )
40  continue;
41 
42  //inform model that we are about to remove an item from the scene
44  mComposition->removeItem( item );
45  item->setIsGroupMember( false );
46  }
47 }
48 
50 {
51  if ( !item )
52  {
53  return;
54  }
55 
56  if ( mItems.contains( item ) )
57  {
58  return;
59  }
60 
61  connect( item, SIGNAL( destroyed() ), this, SLOT( itemDestroyed() ) );
62 
63  mItems.insert( item );
64  item->setSelected( false );
65  item->setIsGroupMember( true );
66 
67  //update extent
68  if ( mBoundingRectangle.isEmpty() ) //we add the first item
69  {
70  mBoundingRectangle = QRectF( 0, 0, item->rect().width(), item->rect().height() );
71  //call method of superclass to avoid repositioning of items
72  QgsComposerItem::setSceneRect( QRectF( item->pos().x(), item->pos().y(), item->rect().width(), item->rect().height() ) );
73 
74  if ( !qgsDoubleNear( item->itemRotation(), 0.0 ) )
75  {
76  setItemRotation( item->itemRotation() );
77  }
78  }
79  else
80  {
81  if ( !qgsDoubleNear( item->itemRotation(), itemRotation() ) )
82  {
83  //items have mixed rotation, so reset rotation of group
84  mBoundingRectangle = mapRectToScene( mBoundingRectangle );
85  setItemRotation( 0 );
86  mBoundingRectangle = mBoundingRectangle.united( item->mapRectToScene( item->rect() ) );
87  //call method of superclass to avoid repositioning of items
88  QgsComposerItem::setSceneRect( mBoundingRectangle );
89  }
90  else
91  {
92  //items have same rotation, so keep rotation of group
93  mBoundingRectangle = mBoundingRectangle.united( mapRectFromItem( item, item->rect() ) );
94  QPointF newPos = mapToScene( mBoundingRectangle.topLeft().x(), mBoundingRectangle.topLeft().y() );
95  mBoundingRectangle = QRectF( 0, 0, mBoundingRectangle.width(), mBoundingRectangle.height() );
96  QgsComposerItem::setSceneRect( QRectF( newPos.x(), newPos.y(), mBoundingRectangle.width(), mBoundingRectangle.height() ) );
97  }
98  }
99 
100 }
101 
103 {
104  Q_FOREACH ( QgsComposerItem* item, mItems )
105  {
106  item->setIsGroupMember( false );
107  item->setSelected( true );
108  }
109  mItems.clear();
110 }
111 
113 {
114  mItems.remove( static_cast<QgsComposerItem*>( sender() ) );
115 }
116 
117 void QgsComposerItemGroup::paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget )
118 {
119  Q_UNUSED( option );
120  Q_UNUSED( widget );
121  drawFrame( painter );
122  if ( isSelected() )
123  {
124  drawSelectionBoxes( painter );
125  }
126 }
127 
128 void QgsComposerItemGroup::setSceneRect( const QRectF& rectangle )
129 {
130  //resize all items in this group
131  //first calculate new group rectangle in current group coordsys
132  QPointF newOrigin = mapFromScene( rectangle.topLeft() );
133  QRectF newRect = QRectF( newOrigin.x(), newOrigin.y(), rectangle.width(), rectangle.height() );
134 
135  Q_FOREACH ( QgsComposerItem* item, mItems )
136  {
137  //each item needs to be scaled relatively to the final size of the group
138  QRectF itemRect = mapRectFromItem( item, item->rect() );
139  QgsComposerUtils::relativeResizeRect( itemRect, rect(), newRect );
140 
141  QPointF newPos = mapToScene( itemRect.topLeft() );
142  item->setSceneRect( QRectF( newPos.x(), newPos.y(), itemRect.width(), itemRect.height() ) );
143  }
144  //lastly, set new rect for group
145  QgsComposerItem::setSceneRect( rectangle );
146 }
147 
148 void QgsComposerItemGroup::setVisibility( const bool visible )
149 {
150  //also set visibility for all items within the group
151  Q_FOREACH ( QgsComposerItem* item, mItems )
152  {
153  item->setVisibility( visible );
154  }
155  //lastly set visibility for group item itself
157 }
158 
160 {
161  if ( !mComposition )
162  {
163  return;
164  }
165 
167  {
168  QPen newPen( pen() );
169  newPen.setStyle( Qt::DashLine );
170  newPen.setColor( QColor( 128, 128, 128, 128 ) );
171  p->setPen( newPen );
172  p->setRenderHint( QPainter::Antialiasing, true );
173  p->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
174  }
175 }
176 
177 bool QgsComposerItemGroup::writeXml( QDomElement& elem, QDomDocument & doc ) const
178 {
179  QDomElement group = doc.createElement( QStringLiteral( "ComposerItemGroup" ) );
180 
181  QSet<QgsComposerItem*>::const_iterator itemIt = mItems.begin();
182  for ( ; itemIt != mItems.end(); ++itemIt )
183  {
184  QDomElement item = doc.createElement( QStringLiteral( "ComposerItemGroupElement" ) );
185  item.setAttribute( QStringLiteral( "uuid" ), ( *itemIt )->uuid() );
186  group.appendChild( item );
187  }
188 
189  elem.appendChild( group );
190 
191  return _writeXml( group, doc );
192 }
193 
194 bool QgsComposerItemGroup::readXml( const QDomElement& itemElem, const QDomDocument& doc )
195 {
196  //restore general composer item properties
197  QDomNodeList composerItemList = itemElem.elementsByTagName( QStringLiteral( "ComposerItem" ) );
198  if ( !composerItemList.isEmpty() )
199  {
200  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
201  _readXml( composerItemElem, doc );
202  }
203 
204  QList<QGraphicsItem *> items = mComposition->items();
205 
206  QDomNodeList elementNodes = itemElem.elementsByTagName( QStringLiteral( "ComposerItemGroupElement" ) );
207  for ( int i = 0; i < elementNodes.count(); ++i )
208  {
209  QDomNode elementNode = elementNodes.at( i );
210  if ( !elementNode.isElement() )
211  continue;
212 
213  QString uuid = elementNode.toElement().attribute( QStringLiteral( "uuid" ) );
214 
215  for ( QList<QGraphicsItem *>::iterator it = items.begin(); it != items.end(); ++it )
216  {
217  QgsComposerItem *item = dynamic_cast<QgsComposerItem *>( *it );
218  if ( item && ( item->mUuid == uuid || item->mTemplateUuid == uuid ) )
219  {
220  addItem( item );
221  break;
222  }
223  }
224  }
225 
226  return true;
227 }
static void relativeResizeRect(QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter)
Resizes a QRectF relative to a resized bounding rectangle.
QgsComposerModel * itemsModel()
Returns the items model attached to the composition.
void removeItems() override
Removes the items but does not delete them.
A item that forms part of a map composition.
void drawFrame(QPainter *p) override
Draw black frame around item.
virtual void setSelected(bool s)
Set selected, selected item should be highlighted.
double itemRotation(const QgsComposerObject::PropertyValueType valueType=QgsComposerObject::EvaluatedValue) const
Returns the current rotation for the composer item.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:196
QgsComposition::PlotStyle plotStyle() const
QSet< QgsComposerItem * > items()
QgsComposerItemGroup(QgsComposition *c)
bool writeXml(QDomElement &elem, QDomDocument &doc) const override
Stores state in Dom node.
bool _writeXml(QDomElement &itemElem, QDomDocument &doc) const
Writes parameter that are not subclass specific in document. Usually called from writeXml methods of ...
virtual void setVisibility(const bool visible) override
Sets visibility for item.
bool readXml(const QDomElement &itemElem, const QDomDocument &doc) override
Sets state from Dom document.
virtual void drawSelectionBoxes(QPainter *p)
Draws additional graphics on selected items.
bool mFrame
True if item fram needs to be painted.
void addItem(QgsComposerItem *item) override
Adds an item to the group.
QString uuid() const
Get item identification name.
bool _readXml(const QDomElement &itemElem, const QDomDocument &doc)
Reads parameter that are not subclass specific in document. Usually called from readXml methods of su...
Graphics scene for map printing.
virtual bool isRemoved() const
Returns whether this item has been removed from the composition.
QgsComposition * mComposition
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr) override
Draw outline and ev. selection handles.
virtual void setItemRotation(const double r, const bool adjustPosition=false)
Sets the item rotation.
void setSceneRect(const QRectF &rectangle) override
Sets this items bound in scene coordinates such that 1 item size units corresponds to 1 scene size un...
virtual void setSceneRect(const QRectF &rectangle)
Sets this items bound in scene coordinates such that 1 item size units corresponds to 1 scene size un...
void setIsGroupMember(const bool isGroupMember)
Sets whether this item is part of a group.
void setItemRemoved(QgsComposerItem *item)
Marks an item as removed from the composition.
virtual void setVisibility(const bool visible)
Sets visibility for item.