Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
qgscomposition.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposition.cpp
3  -------------------
4  begin : January 2005
5  copyright : (C) 2005 by Radim Blazek
6  email : blazek@itc.it
7  ***************************************************************************/
8 /***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include "qgscomposition.h"
18 #include "qgscomposeritem.h"
19 #include "qgscomposermap.h"
20 #include "qgspaperitem.h"
21 #include "qgslogger.h"
22 #include <QDomDocument>
23 #include <QDomElement>
24 #include <QGraphicsRectItem>
25 #include <QSettings>
26 
28  QGraphicsScene( 0 ), mMapRenderer( mapRenderer ), mPlotStyle( QgsComposition::Preview ), mPaperItem( 0 ), mPrintAsRaster( false ), mSnapToGrid( false ),
29  mSnapGridResolution( 0.0 ), mSnapGridOffsetX( 0.0 ), mSnapGridOffsetY( 0.0 ), mActiveCommand( 0 )
30 {
31  setBackgroundBrush( Qt::gray );
32 
33  //set paper item
34  mPaperItem = new QgsPaperItem( 0, 0, 297, 210, this ); //default size A4
35  mPaperItem->setBrush( Qt::white );
36  addItem( mPaperItem );
37  mPaperItem->setZValue( 0 );
38  mPrintResolution = 300; //hardcoded default
40 }
41 
43  QGraphicsScene( 0 ), mMapRenderer( 0 ), mPlotStyle( QgsComposition::Preview ), mPaperItem( 0 ), mPrintAsRaster( false ),
44  mSnapToGrid( false ), mSnapGridResolution( 0.0 ), mSnapGridOffsetX( 0.0 ), mSnapGridOffsetY( 0.0 ), mActiveCommand( 0 )
45 {
47 }
48 
50 {
51  delete mPaperItem;
52 
53  // make sure that all composer items are removed before
54  // this class is deconstructed - to avoid segfaults
55  // when composer items access in destructor composition that isn't valid anymore
56  clear();
57 }
58 
59 void QgsComposition::setPaperSize( double width, double height )
60 {
61  if ( mPaperItem )
62  {
63  mPaperItem->setRect( QRectF( 0, 0, width, height ) );
64  emit paperSizeChanged();
65  }
66 }
67 
69 {
70  return mPaperItem->rect().height();
71 }
72 
74 {
75  return mPaperItem->rect().width();
76 }
77 
78 QgsComposerItem* QgsComposition::composerItemAt( const QPointF & position )
79 {
80  QList<QGraphicsItem *> itemList = items( position );
81  QList<QGraphicsItem *>::iterator itemIt = itemList.begin();
82 
83  for ( ; itemIt != itemList.end(); ++itemIt )
84  {
85  QgsComposerItem* composerItem = dynamic_cast<QgsComposerItem *>( *itemIt );
86  if ( composerItem && composerItem != mPaperItem )
87  {
88  return composerItem;
89  }
90  }
91  return 0;
92 }
93 
94 QList<QgsComposerItem*> QgsComposition::selectedComposerItems()
95 {
96  QList<QgsComposerItem*> composerItemList;
97 
98  QList<QGraphicsItem *> graphicsItemList = selectedItems();
99  QList<QGraphicsItem *>::iterator itemIter = graphicsItemList.begin();
100 
101  for ( ; itemIter != graphicsItemList.end(); ++itemIter )
102  {
103  QgsComposerItem* composerItem = dynamic_cast<QgsComposerItem *>( *itemIter );
104  if ( composerItem )
105  {
106  composerItemList.push_back( composerItem );
107  }
108  }
109 
110  return composerItemList;
111 }
112 
113 QList<const QgsComposerMap*> QgsComposition::composerMapItems() const
114 {
115  QList<const QgsComposerMap*> resultList;
116 
117  QList<QGraphicsItem *> itemList = items();
118  QList<QGraphicsItem *>::iterator itemIt = itemList.begin();
119  for ( ; itemIt != itemList.end(); ++itemIt )
120  {
121  const QgsComposerMap* composerMap = dynamic_cast<const QgsComposerMap *>( *itemIt );
122  if ( composerMap )
123  {
124  resultList.push_back( composerMap );
125  }
126  }
127 
128  return resultList;
129 }
130 
132 {
133  QList<const QgsComposerMap*> resultList;
134 
135  QList<QGraphicsItem *> itemList = items();
136  QList<QGraphicsItem *>::iterator itemIt = itemList.begin();
137  for ( ; itemIt != itemList.end(); ++itemIt )
138  {
139  const QgsComposerMap* composerMap = dynamic_cast<const QgsComposerMap *>( *itemIt );
140  if ( composerMap )
141  {
142  if ( composerMap->id() == id )
143  {
144  return composerMap;
145  }
146  }
147  }
148 
149  return 0;
150 }
151 
152 int QgsComposition::pixelFontSize( double pointSize ) const
153 {
154  //in QgsComposition, one unit = one mm
155  double sizeMillimeters = pointSize * 0.3527;
156  return ( sizeMillimeters + 0.5 ); //round to nearest mm
157 }
158 
159 double QgsComposition::pointFontSize( int pixelSize ) const
160 {
161  double sizePoint = pixelSize / 0.3527;
162  return sizePoint;
163 }
164 
165 bool QgsComposition::writeXML( QDomElement& composerElem, QDomDocument& doc )
166 {
167  if ( composerElem.isNull() )
168  {
169  return false;
170  }
171 
172  QDomElement compositionElem = doc.createElement( "Composition" );
173  if ( mPaperItem )
174  {
175  compositionElem.setAttribute( "paperWidth", mPaperItem->rect().width() );
176  compositionElem.setAttribute( "paperHeight", mPaperItem->rect().height() );
177  }
178 
179  //snapping
180  if ( mSnapToGrid )
181  {
182  compositionElem.setAttribute( "snapping", "1" );
183  }
184  else
185  {
186  compositionElem.setAttribute( "snapping", "0" );
187  }
188  compositionElem.setAttribute( "snapGridResolution", mSnapGridResolution );
189  compositionElem.setAttribute( "snapGridOffsetX", mSnapGridOffsetX );
190  compositionElem.setAttribute( "snapGridOffsetY", mSnapGridOffsetY );
191 
192  compositionElem.setAttribute( "printResolution", mPrintResolution );
193  compositionElem.setAttribute( "printAsRaster", mPrintAsRaster );
194 
195  composerElem.appendChild( compositionElem );
196 
197  return true;
198 }
199 
200 bool QgsComposition::readXML( const QDomElement& compositionElem, const QDomDocument& doc )
201 {
202  if ( compositionElem.isNull() )
203  {
204  return false;
205  }
206 
207  //create paper item
208  bool widthConversionOk, heightConversionOk;
209  double paperWidth = compositionElem.attribute( "paperWidth" ).toDouble( &widthConversionOk );
210  double paperHeight = compositionElem.attribute( "paperHeight" ).toDouble( &heightConversionOk );
211 
212  if ( widthConversionOk && heightConversionOk )
213  {
214  delete mPaperItem;
215  mPaperItem = new QgsPaperItem( 0, 0, paperWidth, paperHeight, this );
216  mPaperItem->setBrush( Qt::white );
217  addItem( mPaperItem );
218  mPaperItem->setZValue( 0 );
219  }
220 
221  //snapping
222  if ( compositionElem.attribute( "snapping" ) == "0" )
223  {
224  mSnapToGrid = false;
225  }
226  else
227  {
228  mSnapToGrid = true;
229  }
230  mSnapGridResolution = compositionElem.attribute( "snapGridResolution" ).toDouble();
231  mSnapGridOffsetX = compositionElem.attribute( "snapGridOffsetX" ).toDouble();
232  mSnapGridOffsetY = compositionElem.attribute( "snapGridOffsetY" ).toDouble();
233  mPrintAsRaster = compositionElem.attribute( "printAsRaster" ).toInt();
234 
235  mPrintResolution = compositionElem.attribute( "printResolution", "300" ).toInt();
236 
237  if ( mPaperItem )
238  {
239  mPaperItem->update();
240  }
241 
242  return true;
243 }
244 
246 {
247  if ( !item )
248  {
249  return;
250  }
251  mItemZList.push_back( item );
252  QgsDebugMsg( QString::number( mItemZList.size() ) );
253  item->setZValue( mItemZList.size() );
254 }
255 
257 {
258  if ( !item )
259  {
260  return;
261  }
262  mItemZList.removeAll( item );
263 }
264 
266 {
267  QList<QgsComposerItem*> selectedItems = selectedComposerItems();
268  QList<QgsComposerItem*>::iterator it = selectedItems.begin();
269  for ( ; it != selectedItems.end(); ++it )
270  {
271  raiseItem( *it );
272  }
273 
274  //update all positions
275  updateZValues();
276  update();
277 }
278 
280 {
281  //search item
282  QMutableLinkedListIterator<QgsComposerItem*> it( mItemZList );
283  if ( it.findNext( item ) )
284  {
285  if ( it.hasNext() )
286  {
287  it.remove();
288  it.next();
289  it.insert( item );
290  }
291  }
292 }
293 
295 {
296  QList<QgsComposerItem*> selectedItems = selectedComposerItems();
297  QList<QgsComposerItem*>::iterator it = selectedItems.begin();
298  for ( ; it != selectedItems.end(); ++it )
299  {
300  lowerItem( *it );
301  }
302 
303  //update all positions
304  updateZValues();
305  update();
306 }
307 
309 {
310  //search item
311  QMutableLinkedListIterator<QgsComposerItem*> it( mItemZList );
312  if ( it.findNext( item ) )
313  {
314  it.previous();
315  if ( it.hasPrevious() )
316  {
317  it.remove();
318  it.previous();
319  it.insert( item );
320  }
321  }
322 }
323 
325 {
326  QList<QgsComposerItem*> selectedItems = selectedComposerItems();
327  QList<QgsComposerItem*>::iterator it = selectedItems.begin();
328 
329  for ( ; it != selectedItems.end(); ++it )
330  {
331  moveItemToTop( *it );
332  }
333 
334  //update all positions
335  updateZValues();
336  update();
337 }
338 
340 {
341  //search item
342  QMutableLinkedListIterator<QgsComposerItem*> it( mItemZList );
343  if ( it.findNext( item ) )
344  {
345  it.remove();
346  }
347  mItemZList.push_back( item );
348 }
349 
351 {
352  QList<QgsComposerItem*> selectedItems = selectedComposerItems();
353  QList<QgsComposerItem*>::iterator it = selectedItems.begin();
354  for ( ; it != selectedItems.end(); ++it )
355  {
356  moveItemToBottom( *it );
357  }
358 
359  //update all positions
360  updateZValues();
361  update();
362 }
363 
365 {
366  //search item
367  QMutableLinkedListIterator<QgsComposerItem*> it( mItemZList );
368  if ( it.findNext( item ) )
369  {
370  it.remove();
371  }
372  mItemZList.push_front( item );
373 }
374 
376 {
377  QList<QgsComposerItem*> selectedItems = selectedComposerItems();
378  if ( selectedItems.size() < 2 )
379  {
380  return;
381  }
382 
383  QRectF selectedItemBBox;
384  if ( boundingRectOfSelectedItems( selectedItemBBox ) != 0 )
385  {
386  return;
387  }
388 
389  double minXCoordinate = selectedItemBBox.left();
390 
391  //align items left to minimum x coordinate
392  QUndoCommand* parentCommand = new QUndoCommand( tr( "Aligned items left" ) );
393  QList<QgsComposerItem*>::iterator align_it = selectedItems.begin();
394  for ( ; align_it != selectedItems.end(); ++align_it )
395  {
396  QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *align_it, "", parentCommand );
397  subcommand->savePreviousState();
398  QTransform itemTransform = ( *align_it )->transform();
399  itemTransform.translate( minXCoordinate - itemTransform.dx(), 0 );
400  ( *align_it )->setTransform( itemTransform );
401  subcommand->saveAfterState();
402  }
403  mUndoStack.push( parentCommand );
404 }
405 
407 {
408  QList<QgsComposerItem*> selectedItems = selectedComposerItems();
409  if ( selectedItems.size() < 2 )
410  {
411  return;
412  }
413 
414  QRectF selectedItemBBox;
415  if ( boundingRectOfSelectedItems( selectedItemBBox ) != 0 )
416  {
417  return;
418  }
419 
420  double averageXCoord = ( selectedItemBBox.left() + selectedItemBBox.right() ) / 2.0;
421 
422  //place items
423  QUndoCommand* parentCommand = new QUndoCommand( tr( "Aligned items hcenter" ) );
424  QList<QgsComposerItem*>::iterator align_it = selectedItems.begin();
425  for ( ; align_it != selectedItems.end(); ++align_it )
426  {
427  QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *align_it, "", parentCommand );
428  subcommand->savePreviousState();
429  QTransform itemTransform = ( *align_it )->transform();
430  itemTransform.translate( averageXCoord - itemTransform.dx() - ( *align_it )->rect().width() / 2.0, 0 );
431  ( *align_it )->setTransform( itemTransform );
432  subcommand->saveAfterState();
433  }
434  mUndoStack.push( parentCommand );
435 }
436 
438 {
439  QList<QgsComposerItem*> selectedItems = selectedComposerItems();
440  if ( selectedItems.size() < 2 )
441  {
442  return;
443  }
444 
445  QRectF selectedItemBBox;
446  if ( boundingRectOfSelectedItems( selectedItemBBox ) != 0 )
447  {
448  return;
449  }
450 
451  double maxXCoordinate = selectedItemBBox.right();
452 
453  //align items right to maximum x coordinate
454  QUndoCommand* parentCommand = new QUndoCommand( tr( "Aligned items right" ) );
455  QList<QgsComposerItem*>::iterator align_it = selectedItems.begin();
456  for ( ; align_it != selectedItems.end(); ++align_it )
457  {
458  QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *align_it, "", parentCommand );
459  subcommand->savePreviousState();
460  QTransform itemTransform = ( *align_it )->transform();
461  itemTransform.translate( maxXCoordinate - itemTransform.dx() - ( *align_it )->rect().width(), 0 );
462  ( *align_it )->setTransform( itemTransform );
463  subcommand->saveAfterState();
464  }
465  mUndoStack.push( parentCommand );
466 }
467 
469 {
470  QList<QgsComposerItem*> selectedItems = selectedComposerItems();
471  if ( selectedItems.size() < 2 )
472  {
473  return;
474  }
475 
476  QRectF selectedItemBBox;
477  if ( boundingRectOfSelectedItems( selectedItemBBox ) != 0 )
478  {
479  return;
480  }
481 
482  double minYCoordinate = selectedItemBBox.top();
483 
484  QUndoCommand* parentCommand = new QUndoCommand( tr( "Aligned items top" ) );
485  QList<QgsComposerItem*>::iterator align_it = selectedItems.begin();
486  for ( ; align_it != selectedItems.end(); ++align_it )
487  {
488  QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *align_it, "", parentCommand );
489  subcommand->savePreviousState();
490  QTransform itemTransform = ( *align_it )->transform();
491  itemTransform.translate( 0, minYCoordinate - itemTransform.dy() );
492  ( *align_it )->setTransform( itemTransform );
493  subcommand->saveAfterState();
494  }
495  mUndoStack.push( parentCommand );
496 }
497 
499 {
500  QList<QgsComposerItem*> selectedItems = selectedComposerItems();
501  if ( selectedItems.size() < 2 )
502  {
503  return;
504  }
505 
506  QRectF selectedItemBBox;
507  if ( boundingRectOfSelectedItems( selectedItemBBox ) != 0 )
508  {
509  return;
510  }
511 
512  double averageYCoord = ( selectedItemBBox.top() + selectedItemBBox.bottom() ) / 2.0;
513  QUndoCommand* parentCommand = new QUndoCommand( tr( "Aligned items vcenter" ) );
514  QList<QgsComposerItem*>::iterator align_it = selectedItems.begin();
515  for ( ; align_it != selectedItems.end(); ++align_it )
516  {
517  QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *align_it, "", parentCommand );
518  subcommand->savePreviousState();
519  QTransform itemTransform = ( *align_it )->transform();
520  itemTransform.translate( 0, averageYCoord - itemTransform.dy() - ( *align_it )->rect().height() / 2 );
521  ( *align_it )->setTransform( itemTransform );
522  subcommand->saveAfterState();
523  }
524  mUndoStack.push( parentCommand );
525 }
526 
528 {
529  QList<QgsComposerItem*> selectedItems = selectedComposerItems();
530  if ( selectedItems.size() < 2 )
531  {
532  return;
533  }
534 
535  QRectF selectedItemBBox;
536  if ( boundingRectOfSelectedItems( selectedItemBBox ) != 0 )
537  {
538  return;
539  }
540 
541  double maxYCoord = selectedItemBBox.bottom();
542  QUndoCommand* parentCommand = new QUndoCommand( tr( "Aligned items bottom" ) );
543  QList<QgsComposerItem*>::iterator align_it = selectedItems.begin();
544  for ( ; align_it != selectedItems.end(); ++align_it )
545  {
546  QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *align_it, "", parentCommand );
547  subcommand->savePreviousState();
548  QTransform itemTransform = ( *align_it )->transform();
549  itemTransform.translate( 0, maxYCoord - itemTransform.dy() - ( *align_it )->rect().height() );
550  ( *align_it )->setTransform( itemTransform );
551  subcommand->saveAfterState();
552  }
553  mUndoStack.push( parentCommand );
554 }
555 
557 {
558  int counter = 1;
559  QLinkedList<QgsComposerItem*>::iterator it = mItemZList.begin();
560  QgsComposerItem* currentItem = 0;
561 
562  QUndoCommand* parentCommand = new QUndoCommand( tr( "Item z-order changed" ) );
563  for ( ; it != mItemZList.end(); ++it )
564  {
565  currentItem = *it;
566  if ( currentItem )
567  {
568  QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *it, "", parentCommand );
569  subcommand->savePreviousState();
570  currentItem->setZValue( counter );
571  subcommand->saveAfterState();
572  }
573  ++counter;
574  }
575  mUndoStack.push( parentCommand );
576 }
577 
579 {
580  if ( mItemZList.size() < 2 )
581  {
582  return;
583  }
584 
585  QLinkedList<QgsComposerItem*>::const_iterator lIt = mItemZList.constBegin();
586  QLinkedList<QgsComposerItem*> sortedList;
587 
588  for ( ; lIt != mItemZList.constEnd(); ++lIt )
589  {
590  QLinkedList<QgsComposerItem*>::iterator insertIt = sortedList.begin();
591  for ( ; insertIt != sortedList.end(); ++insertIt )
592  {
593  if (( *lIt )->zValue() < ( *insertIt )->zValue() )
594  {
595  break;
596  }
597  }
598  sortedList.insert( insertIt, ( *lIt ) );
599  }
600 
601  mItemZList = sortedList;
602 }
603 
604 QPointF QgsComposition::snapPointToGrid( const QPointF& scenePoint ) const
605 {
606  if ( !mSnapToGrid || mSnapGridResolution <= 0 )
607  {
608  return scenePoint;
609  }
610 
611  //snap x coordinate //todo: add support for x- and y- offset
612  int xRatio = ( int )(( scenePoint.x() - mSnapGridOffsetX ) / mSnapGridResolution + 0.5 );
613  int yRatio = ( int )(( scenePoint.y() - mSnapGridOffsetY ) / mSnapGridResolution + 0.5 );
614 
615  return QPointF( xRatio * mSnapGridResolution + mSnapGridOffsetX, yRatio * mSnapGridResolution + mSnapGridOffsetY );
616 }
617 
619 {
620  QList<QgsComposerItem*> selectedItems = selectedComposerItems();
621  if ( selectedItems.size() < 1 )
622  {
623  return 1;
624  }
625 
626  //set the box to the first item
627  QgsComposerItem* currentItem = selectedItems.at( 0 );
628  double minX = currentItem->transform().dx();
629  double minY = currentItem->transform().dy();
630  double maxX = minX + currentItem->rect().width();
631  double maxY = minY + currentItem->rect().height();
632 
633  double currentMinX, currentMinY, currentMaxX, currentMaxY;
634 
635  for ( int i = 1; i < selectedItems.size(); ++i )
636  {
637  currentItem = selectedItems.at( i );
638  currentMinX = currentItem->transform().dx();
639  currentMinY = currentItem->transform().dy();
640  currentMaxX = currentMinX + currentItem->rect().width();
641  currentMaxY = currentMinY + currentItem->rect().height();
642 
643  if ( currentMinX < minX )
644  minX = currentMinX;
645  if ( currentMaxX > maxX )
646  maxX = currentMaxX;
647  if ( currentMinY < minY )
648  minY = currentMinY;
649  if ( currentMaxY > maxY )
650  maxY = currentMaxY;
651  }
652 
653  bRect.setTopLeft( QPointF( minX, minY ) );
654  bRect.setBottomRight( QPointF( maxX, maxY ) );
655  return 0;
656 }
657 
659 {
660  mSnapToGrid = b;
661  if ( mPaperItem )
662  {
663  mPaperItem->update();
664  }
665 }
666 
668 {
670  if ( mPaperItem )
671  {
672  mPaperItem->update();
673  }
674 }
675 
677 {
678  mSnapGridOffsetX = offset;
679  if ( mPaperItem )
680  {
681  mPaperItem->update();
682  }
683 }
684 
686 {
687  mSnapGridOffsetY = offset;
688  if ( mPaperItem )
689  {
690  mPaperItem->update();
691  }
692 }
693 
694 void QgsComposition::setGridPen( const QPen& p )
695 {
696  mGridPen = p;
697  if ( mPaperItem )
698  {
699  mPaperItem->update();
700  }
702 }
703 
705 {
706  mGridStyle = s;
707  if ( mPaperItem )
708  {
709  mPaperItem->update();
710  }
712 }
713 
715 {
716  //read grid style, grid color and pen width from settings
717  QSettings s;
718 
719  QString gridStyleString;
720  int red, green, blue;
721  double penWidth;
722 
723  gridStyleString = s.value( "/qgis/composerGridStyle", "Dots" ).toString();
724  penWidth = s.value( "/qgis/composerGridWidth", 0.5 ).toDouble();
725  red = s.value( "/qgis/composerGridRed", 0 ).toInt();
726  green = s.value( "/qgis/composerGridGreen", 0 ).toInt();
727  blue = s.value( "/qgis/composerGridBlue", 0 ).toInt();
728 
729  mGridPen.setColor( QColor( red, green, blue ) );
730  mGridPen.setWidthF( penWidth );
731 
732  if ( gridStyleString == "Dots" )
733  {
734  mGridStyle = Dots;
735  }
736  else if ( gridStyleString == "Crosses" )
737  {
739  }
740  else
741  {
742  mGridStyle = Solid;
743  }
744 }
745 
747 {
748  //store grid appearance settings
749  QSettings s;
750  s.setValue( "/qgis/composerGridWidth", mGridPen.widthF() );
751  s.setValue( "/qgis/composerGridRed", mGridPen.color().red() );
752  s.setValue( "/qgis/composerGridGreen", mGridPen.color().green() );
753  s.setValue( "/qgis/composerGridBlue", mGridPen.color().blue() );
754 
755  if ( mGridStyle == Solid )
756  {
757  s.setValue( "/qgis/composerGridStyle", "Solid" );
758  }
759  else if ( mGridStyle == Dots )
760  {
761  s.setValue( "/qgis/composerGridStyle", "Dots" );
762  }
763  else if ( mGridStyle == Crosses )
764  {
765  s.setValue( "/qgis/composerGridStyle", "Crosses" );
766  }
767 }
768 
770 {
771  delete mActiveCommand;
772  if ( !item )
773  {
774  mActiveCommand = 0;
775  return;
776  }
777 
779  {
780  mActiveCommand = new QgsComposerItemCommand( item, commandText );
781  }
782  else
783  {
784  mActiveCommand = new QgsComposerMergeCommand( c, item, commandText );
785  }
787 }
788 
790 {
791  if ( mActiveCommand )
792  {
794  if ( mActiveCommand->containsChange() ) //protect against empty commands
795  {
796  mUndoStack.push( mActiveCommand );
797  }
798  else
799  {
800  delete mActiveCommand;
801  }
802  mActiveCommand = 0;
803  }
804 }
805 
807 {
808  delete mActiveCommand;
809  mActiveCommand = 0;
810 }