00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "qgscomposition.h"
00018 #include "qgscomposeritem.h"
00019 #include "qgspaperitem.h"
00020 #include "qgscomposerarrow.h"
00021 #include "qgscomposerlabel.h"
00022 #include "qgscomposerlegend.h"
00023 #include "qgscomposermap.h"
00024 #include "qgscomposeritemgroup.h"
00025 #include "qgscomposerpicture.h"
00026 #include "qgscomposerscalebar.h"
00027 #include "qgscomposershape.h"
00028 #include "qgscomposerattributetable.h"
00029 #include "qgslogger.h"
00030 #include <QDomDocument>
00031 #include <QDomElement>
00032 #include <QGraphicsRectItem>
00033 #include <QSettings>
00034
00035 QgsComposition::QgsComposition( QgsMapRenderer* mapRenderer ):
00036 QGraphicsScene( 0 ), mMapRenderer( mapRenderer ), mPlotStyle( QgsComposition::Preview ), mPaperItem( 0 ), mPrintAsRaster( false ), mSelectionTolerance( 0.0 ),
00037 mSnapToGrid( false ), mSnapGridResolution( 0.0 ), mSnapGridOffsetX( 0.0 ), mSnapGridOffsetY( 0.0 ), mActiveCommand( 0 )
00038 {
00039 setBackgroundBrush( Qt::gray );
00040
00041
00042 mPaperItem = new QgsPaperItem( 0, 0, 297, 210, this );
00043 mPaperItem->setBrush( Qt::white );
00044 addItem( mPaperItem );
00045 mPaperItem->setZValue( 0 );
00046 mPrintResolution = 300;
00047 loadSettings();
00048 }
00049
00050 QgsComposition::QgsComposition():
00051 QGraphicsScene( 0 ), mMapRenderer( 0 ), mPlotStyle( QgsComposition::Preview ), mPaperItem( 0 ), mPrintAsRaster( false ),
00052 mSelectionTolerance( 0.0 ), mSnapToGrid( false ), mSnapGridResolution( 0.0 ), mSnapGridOffsetX( 0.0 ), mSnapGridOffsetY( 0.0 ), mActiveCommand( 0 )
00053 {
00054 loadSettings();
00055 }
00056
00057 QgsComposition::~QgsComposition()
00058 {
00059 delete mPaperItem;
00060
00061
00062
00063
00064 clear();
00065 }
00066
00067 void QgsComposition::setPaperSize( double width, double height )
00068 {
00069 if ( mPaperItem )
00070 {
00071 mPaperItem->setRect( QRectF( 0, 0, width, height ) );
00072 emit paperSizeChanged();
00073 }
00074 }
00075
00076 double QgsComposition::paperHeight() const
00077 {
00078 return mPaperItem->rect().height();
00079 }
00080
00081 double QgsComposition::paperWidth() const
00082 {
00083 return mPaperItem->rect().width();
00084 }
00085
00086 QgsComposerItem* QgsComposition::composerItemAt( const QPointF & position )
00087 {
00088 QList<QGraphicsItem*> itemList;
00089 if ( mSelectionTolerance <= 0.0 )
00090 {
00091 itemList = items( position );
00092 }
00093 else
00094 {
00095 itemList = items( QRectF( position.x() - mSelectionTolerance, position.y() - mSelectionTolerance, 2 * mSelectionTolerance, 2 * mSelectionTolerance ),
00096 Qt::IntersectsItemShape, Qt::DescendingOrder );
00097 }
00098 QList<QGraphicsItem *>::iterator itemIt = itemList.begin();
00099
00100 for ( ; itemIt != itemList.end(); ++itemIt )
00101 {
00102 QgsComposerItem* composerItem = dynamic_cast<QgsComposerItem *>( *itemIt );
00103 if ( composerItem && composerItem != mPaperItem )
00104 {
00105 return composerItem;
00106 }
00107 }
00108 return 0;
00109 }
00110
00111 QList<QgsComposerItem*> QgsComposition::selectedComposerItems()
00112 {
00113 QList<QgsComposerItem*> composerItemList;
00114
00115 QList<QGraphicsItem *> graphicsItemList = selectedItems();
00116 QList<QGraphicsItem *>::iterator itemIter = graphicsItemList.begin();
00117
00118 for ( ; itemIter != graphicsItemList.end(); ++itemIter )
00119 {
00120 QgsComposerItem* composerItem = dynamic_cast<QgsComposerItem *>( *itemIter );
00121 if ( composerItem )
00122 {
00123 composerItemList.push_back( composerItem );
00124 }
00125 }
00126
00127 return composerItemList;
00128 }
00129
00130 QList<const QgsComposerMap*> QgsComposition::composerMapItems() const
00131 {
00132 QList<const QgsComposerMap*> resultList;
00133
00134 QList<QGraphicsItem *> itemList = items();
00135 QList<QGraphicsItem *>::iterator itemIt = itemList.begin();
00136 for ( ; itemIt != itemList.end(); ++itemIt )
00137 {
00138 const QgsComposerMap* composerMap = dynamic_cast<const QgsComposerMap *>( *itemIt );
00139 if ( composerMap )
00140 {
00141 resultList.push_back( composerMap );
00142 }
00143 }
00144
00145 return resultList;
00146 }
00147
00148 const QgsComposerMap* QgsComposition::getComposerMapById( int id ) const
00149 {
00150 QList<const QgsComposerMap*> resultList;
00151
00152 QList<QGraphicsItem *> itemList = items();
00153 QList<QGraphicsItem *>::iterator itemIt = itemList.begin();
00154 for ( ; itemIt != itemList.end(); ++itemIt )
00155 {
00156 const QgsComposerMap* composerMap = dynamic_cast<const QgsComposerMap *>( *itemIt );
00157 if ( composerMap )
00158 {
00159 if ( composerMap->id() == id )
00160 {
00161 return composerMap;
00162 }
00163 }
00164 }
00165
00166 return 0;
00167 }
00168
00169 int QgsComposition::pixelFontSize( double pointSize ) const
00170 {
00171
00172 double sizeMillimeters = pointSize * 0.3527;
00173 return ( sizeMillimeters + 0.5 );
00174 }
00175
00176 double QgsComposition::pointFontSize( int pixelSize ) const
00177 {
00178 double sizePoint = pixelSize / 0.3527;
00179 return sizePoint;
00180 }
00181
00182 bool QgsComposition::writeXML( QDomElement& composerElem, QDomDocument& doc )
00183 {
00184 if ( composerElem.isNull() )
00185 {
00186 return false;
00187 }
00188
00189 QDomElement compositionElem = doc.createElement( "Composition" );
00190 if ( mPaperItem )
00191 {
00192 compositionElem.setAttribute( "paperWidth", mPaperItem->rect().width() );
00193 compositionElem.setAttribute( "paperHeight", mPaperItem->rect().height() );
00194 }
00195
00196
00197 if ( mSnapToGrid )
00198 {
00199 compositionElem.setAttribute( "snapping", "1" );
00200 }
00201 else
00202 {
00203 compositionElem.setAttribute( "snapping", "0" );
00204 }
00205 compositionElem.setAttribute( "snapGridResolution", mSnapGridResolution );
00206 compositionElem.setAttribute( "snapGridOffsetX", mSnapGridOffsetX );
00207 compositionElem.setAttribute( "snapGridOffsetY", mSnapGridOffsetY );
00208
00209 compositionElem.setAttribute( "printResolution", mPrintResolution );
00210 compositionElem.setAttribute( "printAsRaster", mPrintAsRaster );
00211
00212 composerElem.appendChild( compositionElem );
00213
00214 return true;
00215 }
00216
00217 bool QgsComposition::readXML( const QDomElement& compositionElem, const QDomDocument& doc )
00218 {
00219 Q_UNUSED( doc );
00220 if ( compositionElem.isNull() )
00221 {
00222 return false;
00223 }
00224
00225
00226 bool widthConversionOk, heightConversionOk;
00227 double paperWidth = compositionElem.attribute( "paperWidth" ).toDouble( &widthConversionOk );
00228 double paperHeight = compositionElem.attribute( "paperHeight" ).toDouble( &heightConversionOk );
00229
00230 if ( widthConversionOk && heightConversionOk )
00231 {
00232 delete mPaperItem;
00233 mPaperItem = new QgsPaperItem( 0, 0, paperWidth, paperHeight, this );
00234 mPaperItem->setBrush( Qt::white );
00235 addItem( mPaperItem );
00236 mPaperItem->setZValue( 0 );
00237 }
00238
00239
00240 if ( compositionElem.attribute( "snapping" ) == "0" )
00241 {
00242 mSnapToGrid = false;
00243 }
00244 else
00245 {
00246 mSnapToGrid = true;
00247 }
00248 mSnapGridResolution = compositionElem.attribute( "snapGridResolution" ).toDouble();
00249 mSnapGridOffsetX = compositionElem.attribute( "snapGridOffsetX" ).toDouble();
00250 mSnapGridOffsetY = compositionElem.attribute( "snapGridOffsetY" ).toDouble();
00251 mPrintAsRaster = compositionElem.attribute( "printAsRaster" ).toInt();
00252
00253 mPrintResolution = compositionElem.attribute( "printResolution", "300" ).toInt();
00254
00255 if ( mPaperItem )
00256 {
00257 mPaperItem->update();
00258 }
00259
00260 return true;
00261 }
00262
00263 void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocument& doc, QMap< QgsComposerMap*, int >* mapsToRestore,
00264 bool addUndoCommands, QPointF* pos )
00265 {
00266 QDomNodeList composerLabelList = elem.elementsByTagName( "ComposerLabel" );
00267 for ( int i = 0; i < composerLabelList.size(); ++i )
00268 {
00269 QDomElement currentComposerLabelElem = composerLabelList.at( i ).toElement();
00270 QgsComposerLabel* newLabel = new QgsComposerLabel( this );
00271 newLabel->readXML( currentComposerLabelElem, doc );
00272 if ( pos )
00273 {
00274 newLabel->setItemPosition( pos->x(), pos->y() );
00275 }
00276 addComposerLabel( newLabel );
00277 if ( addUndoCommands )
00278 {
00279 pushAddRemoveCommand( newLabel, tr( "Label added" ) );
00280 }
00281 }
00282
00283 QDomNodeList composerMapList = elem.elementsByTagName( "ComposerMap" );
00284 for ( int i = 0; i < composerMapList.size(); ++i )
00285 {
00286 QDomElement currentComposerMapElem = composerMapList.at( i ).toElement();
00287 QgsComposerMap* newMap = new QgsComposerMap( this );
00288 newMap->readXML( currentComposerMapElem, doc );
00289
00290 if ( mapsToRestore )
00291 {
00292 mapsToRestore->insert( newMap, ( int )( newMap->previewMode() ) );
00293 newMap->setPreviewMode( QgsComposerMap::Rectangle );
00294 }
00295 addComposerMap( newMap, false );
00296
00297 if ( pos )
00298 {
00299 newMap->setItemPosition( pos->x(), pos->y() );
00300 }
00301
00302 if ( addUndoCommands )
00303 {
00304 pushAddRemoveCommand( newMap, tr( "Map added" ) );
00305 }
00306 }
00307
00308 QDomNodeList composerArrowList = elem.elementsByTagName( "ComposerArrow" );
00309 for ( int i = 0; i < composerArrowList.size(); ++i )
00310 {
00311 QDomElement currentComposerArrowElem = composerArrowList.at( i ).toElement();
00312 QgsComposerArrow* newArrow = new QgsComposerArrow( this );
00313 newArrow->readXML( currentComposerArrowElem, doc );
00314 if ( pos )
00315 {
00316 newArrow->setItemPosition( pos->x(), pos->y() );
00317 }
00318 addComposerArrow( newArrow );
00319 if ( addUndoCommands )
00320 {
00321 pushAddRemoveCommand( newArrow, tr( "Arrow added" ) );
00322 }
00323 }
00324
00325 QDomNodeList composerScaleBarList = elem.elementsByTagName( "ComposerScaleBar" );
00326 for ( int i = 0; i < composerScaleBarList.size(); ++i )
00327 {
00328 QDomElement currentComposerScaleBarElem = composerScaleBarList.at( i ).toElement();
00329 QgsComposerScaleBar* newScaleBar = new QgsComposerScaleBar( this );
00330 newScaleBar->readXML( currentComposerScaleBarElem, doc );
00331 if ( pos )
00332 {
00333 newScaleBar->setItemPosition( pos->x(), pos->y() );
00334 }
00335 addComposerScaleBar( newScaleBar );
00336 if ( addUndoCommands )
00337 {
00338 pushAddRemoveCommand( newScaleBar, tr( "Scale bar added" ) );
00339 }
00340 }
00341
00342 QDomNodeList composerShapeList = elem.elementsByTagName( "ComposerShape" );
00343 for ( int i = 0; i < composerShapeList.size(); ++i )
00344 {
00345 QDomElement currentComposerShapeElem = composerShapeList.at( i ).toElement();
00346 QgsComposerShape* newShape = new QgsComposerShape( this );
00347 newShape->readXML( currentComposerShapeElem, doc );
00348 if ( pos )
00349 {
00350 newShape->setItemPosition( pos->x(), pos->y() );
00351 }
00352 addComposerShape( newShape );
00353 if ( addUndoCommands )
00354 {
00355 pushAddRemoveCommand( newShape, tr( "Shape added" ) );
00356 }
00357 }
00358
00359 QDomNodeList composerPictureList = elem.elementsByTagName( "ComposerPicture" );
00360 for ( int i = 0; i < composerPictureList.size(); ++i )
00361 {
00362 QDomElement currentComposerPictureElem = composerPictureList.at( i ).toElement();
00363 QgsComposerPicture* newPicture = new QgsComposerPicture( this );
00364 newPicture->readXML( currentComposerPictureElem, doc );
00365 if ( pos )
00366 {
00367 newPicture->setItemPosition( pos->x(), pos->y() );
00368 }
00369 addComposerPicture( newPicture );
00370 if ( addUndoCommands )
00371 {
00372 pushAddRemoveCommand( newPicture, tr( "Picture added" ) );
00373 }
00374 }
00375
00376 QDomNodeList composerLegendList = elem.elementsByTagName( "ComposerLegend" );
00377 for ( int i = 0; i < composerLegendList.size(); ++i )
00378 {
00379 QDomElement currentComposerLegendElem = composerLegendList.at( i ).toElement();
00380 QgsComposerLegend* newLegend = new QgsComposerLegend( this );
00381 newLegend->readXML( currentComposerLegendElem, doc );
00382 if ( pos )
00383 {
00384 newLegend->setItemPosition( pos->x(), pos->y() );
00385 }
00386 addComposerLegend( newLegend );
00387 if ( addUndoCommands )
00388 {
00389 pushAddRemoveCommand( newLegend, tr( "Legend added" ) );
00390 }
00391 }
00392
00393 QDomNodeList composerTableList = elem.elementsByTagName( "ComposerAttributeTable" );
00394 for ( int i = 0; i < composerTableList.size(); ++i )
00395 {
00396 QDomElement currentComposerTableElem = composerTableList.at( i ).toElement();
00397 QgsComposerAttributeTable* newTable = new QgsComposerAttributeTable( this );
00398 newTable->readXML( currentComposerTableElem, doc );
00399 if ( pos )
00400 {
00401 newTable->setItemPosition( pos->x(), pos->y() );
00402 }
00403 addComposerTable( newTable );
00404 if ( addUndoCommands )
00405 {
00406 pushAddRemoveCommand( newTable, tr( "Table added" ) );
00407 }
00408 }
00409 }
00410
00411 void QgsComposition::addItemToZList( QgsComposerItem* item )
00412 {
00413 if ( !item )
00414 {
00415 return;
00416 }
00417 mItemZList.push_back( item );
00418 QgsDebugMsg( QString::number( mItemZList.size() ) );
00419 item->setZValue( mItemZList.size() );
00420 }
00421
00422 void QgsComposition::removeItemFromZList( QgsComposerItem* item )
00423 {
00424 if ( !item )
00425 {
00426 return;
00427 }
00428 mItemZList.removeAll( item );
00429 }
00430
00431 void QgsComposition::raiseSelectedItems()
00432 {
00433 QList<QgsComposerItem*> selectedItems = selectedComposerItems();
00434 QList<QgsComposerItem*>::iterator it = selectedItems.begin();
00435 for ( ; it != selectedItems.end(); ++it )
00436 {
00437 raiseItem( *it );
00438 }
00439
00440
00441 updateZValues();
00442 update();
00443 }
00444
00445 void QgsComposition::raiseItem( QgsComposerItem* item )
00446 {
00447
00448 QMutableLinkedListIterator<QgsComposerItem*> it( mItemZList );
00449 if ( it.findNext( item ) )
00450 {
00451 if ( it.hasNext() )
00452 {
00453 it.remove();
00454 it.next();
00455 it.insert( item );
00456 }
00457 }
00458 }
00459
00460 void QgsComposition::lowerSelectedItems()
00461 {
00462 QList<QgsComposerItem*> selectedItems = selectedComposerItems();
00463 QList<QgsComposerItem*>::iterator it = selectedItems.begin();
00464 for ( ; it != selectedItems.end(); ++it )
00465 {
00466 lowerItem( *it );
00467 }
00468
00469
00470 updateZValues();
00471 update();
00472 }
00473
00474 void QgsComposition::lowerItem( QgsComposerItem* item )
00475 {
00476
00477 QMutableLinkedListIterator<QgsComposerItem*> it( mItemZList );
00478 if ( it.findNext( item ) )
00479 {
00480 it.previous();
00481 if ( it.hasPrevious() )
00482 {
00483 it.remove();
00484 it.previous();
00485 it.insert( item );
00486 }
00487 }
00488 }
00489
00490 void QgsComposition::moveSelectedItemsToTop()
00491 {
00492 QList<QgsComposerItem*> selectedItems = selectedComposerItems();
00493 QList<QgsComposerItem*>::iterator it = selectedItems.begin();
00494
00495 for ( ; it != selectedItems.end(); ++it )
00496 {
00497 moveItemToTop( *it );
00498 }
00499
00500
00501 updateZValues();
00502 update();
00503 }
00504
00505 void QgsComposition::moveItemToTop( QgsComposerItem* item )
00506 {
00507
00508 QMutableLinkedListIterator<QgsComposerItem*> it( mItemZList );
00509 if ( it.findNext( item ) )
00510 {
00511 it.remove();
00512 }
00513 mItemZList.push_back( item );
00514 }
00515
00516 void QgsComposition::moveSelectedItemsToBottom()
00517 {
00518 QList<QgsComposerItem*> selectedItems = selectedComposerItems();
00519 QList<QgsComposerItem*>::iterator it = selectedItems.begin();
00520 for ( ; it != selectedItems.end(); ++it )
00521 {
00522 moveItemToBottom( *it );
00523 }
00524
00525
00526 updateZValues();
00527 update();
00528 }
00529
00530 void QgsComposition::moveItemToBottom( QgsComposerItem* item )
00531 {
00532
00533 QMutableLinkedListIterator<QgsComposerItem*> it( mItemZList );
00534 if ( it.findNext( item ) )
00535 {
00536 it.remove();
00537 }
00538 mItemZList.push_front( item );
00539 }
00540
00541 void QgsComposition::alignSelectedItemsLeft()
00542 {
00543 QList<QgsComposerItem*> selectedItems = selectedComposerItems();
00544 if ( selectedItems.size() < 2 )
00545 {
00546 return;
00547 }
00548
00549 QRectF selectedItemBBox;
00550 if ( boundingRectOfSelectedItems( selectedItemBBox ) != 0 )
00551 {
00552 return;
00553 }
00554
00555 double minXCoordinate = selectedItemBBox.left();
00556
00557
00558 QUndoCommand* parentCommand = new QUndoCommand( tr( "Aligned items left" ) );
00559 QList<QgsComposerItem*>::iterator align_it = selectedItems.begin();
00560 for ( ; align_it != selectedItems.end(); ++align_it )
00561 {
00562 QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *align_it, "", parentCommand );
00563 subcommand->savePreviousState();
00564 QTransform itemTransform = ( *align_it )->transform();
00565 itemTransform.translate( minXCoordinate - itemTransform.dx(), 0 );
00566 ( *align_it )->setTransform( itemTransform );
00567 subcommand->saveAfterState();
00568 }
00569 mUndoStack.push( parentCommand );
00570 }
00571
00572 void QgsComposition::alignSelectedItemsHCenter()
00573 {
00574 QList<QgsComposerItem*> selectedItems = selectedComposerItems();
00575 if ( selectedItems.size() < 2 )
00576 {
00577 return;
00578 }
00579
00580 QRectF selectedItemBBox;
00581 if ( boundingRectOfSelectedItems( selectedItemBBox ) != 0 )
00582 {
00583 return;
00584 }
00585
00586 double averageXCoord = ( selectedItemBBox.left() + selectedItemBBox.right() ) / 2.0;
00587
00588
00589 QUndoCommand* parentCommand = new QUndoCommand( tr( "Aligned items hcenter" ) );
00590 QList<QgsComposerItem*>::iterator align_it = selectedItems.begin();
00591 for ( ; align_it != selectedItems.end(); ++align_it )
00592 {
00593 QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *align_it, "", parentCommand );
00594 subcommand->savePreviousState();
00595 QTransform itemTransform = ( *align_it )->transform();
00596 itemTransform.translate( averageXCoord - itemTransform.dx() - ( *align_it )->rect().width() / 2.0, 0 );
00597 ( *align_it )->setTransform( itemTransform );
00598 subcommand->saveAfterState();
00599 }
00600 mUndoStack.push( parentCommand );
00601 }
00602
00603 void QgsComposition::alignSelectedItemsRight()
00604 {
00605 QList<QgsComposerItem*> selectedItems = selectedComposerItems();
00606 if ( selectedItems.size() < 2 )
00607 {
00608 return;
00609 }
00610
00611 QRectF selectedItemBBox;
00612 if ( boundingRectOfSelectedItems( selectedItemBBox ) != 0 )
00613 {
00614 return;
00615 }
00616
00617 double maxXCoordinate = selectedItemBBox.right();
00618
00619
00620 QUndoCommand* parentCommand = new QUndoCommand( tr( "Aligned items right" ) );
00621 QList<QgsComposerItem*>::iterator align_it = selectedItems.begin();
00622 for ( ; align_it != selectedItems.end(); ++align_it )
00623 {
00624 QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *align_it, "", parentCommand );
00625 subcommand->savePreviousState();
00626 QTransform itemTransform = ( *align_it )->transform();
00627 itemTransform.translate( maxXCoordinate - itemTransform.dx() - ( *align_it )->rect().width(), 0 );
00628 ( *align_it )->setTransform( itemTransform );
00629 subcommand->saveAfterState();
00630 }
00631 mUndoStack.push( parentCommand );
00632 }
00633
00634 void QgsComposition::alignSelectedItemsTop()
00635 {
00636 QList<QgsComposerItem*> selectedItems = selectedComposerItems();
00637 if ( selectedItems.size() < 2 )
00638 {
00639 return;
00640 }
00641
00642 QRectF selectedItemBBox;
00643 if ( boundingRectOfSelectedItems( selectedItemBBox ) != 0 )
00644 {
00645 return;
00646 }
00647
00648 double minYCoordinate = selectedItemBBox.top();
00649
00650 QUndoCommand* parentCommand = new QUndoCommand( tr( "Aligned items top" ) );
00651 QList<QgsComposerItem*>::iterator align_it = selectedItems.begin();
00652 for ( ; align_it != selectedItems.end(); ++align_it )
00653 {
00654 QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *align_it, "", parentCommand );
00655 subcommand->savePreviousState();
00656 QTransform itemTransform = ( *align_it )->transform();
00657 itemTransform.translate( 0, minYCoordinate - itemTransform.dy() );
00658 ( *align_it )->setTransform( itemTransform );
00659 subcommand->saveAfterState();
00660 }
00661 mUndoStack.push( parentCommand );
00662 }
00663
00664 void QgsComposition::alignSelectedItemsVCenter()
00665 {
00666 QList<QgsComposerItem*> selectedItems = selectedComposerItems();
00667 if ( selectedItems.size() < 2 )
00668 {
00669 return;
00670 }
00671
00672 QRectF selectedItemBBox;
00673 if ( boundingRectOfSelectedItems( selectedItemBBox ) != 0 )
00674 {
00675 return;
00676 }
00677
00678 double averageYCoord = ( selectedItemBBox.top() + selectedItemBBox.bottom() ) / 2.0;
00679 QUndoCommand* parentCommand = new QUndoCommand( tr( "Aligned items vcenter" ) );
00680 QList<QgsComposerItem*>::iterator align_it = selectedItems.begin();
00681 for ( ; align_it != selectedItems.end(); ++align_it )
00682 {
00683 QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *align_it, "", parentCommand );
00684 subcommand->savePreviousState();
00685 QTransform itemTransform = ( *align_it )->transform();
00686 itemTransform.translate( 0, averageYCoord - itemTransform.dy() - ( *align_it )->rect().height() / 2 );
00687 ( *align_it )->setTransform( itemTransform );
00688 subcommand->saveAfterState();
00689 }
00690 mUndoStack.push( parentCommand );
00691 }
00692
00693 void QgsComposition::alignSelectedItemsBottom()
00694 {
00695 QList<QgsComposerItem*> selectedItems = selectedComposerItems();
00696 if ( selectedItems.size() < 2 )
00697 {
00698 return;
00699 }
00700
00701 QRectF selectedItemBBox;
00702 if ( boundingRectOfSelectedItems( selectedItemBBox ) != 0 )
00703 {
00704 return;
00705 }
00706
00707 double maxYCoord = selectedItemBBox.bottom();
00708 QUndoCommand* parentCommand = new QUndoCommand( tr( "Aligned items bottom" ) );
00709 QList<QgsComposerItem*>::iterator align_it = selectedItems.begin();
00710 for ( ; align_it != selectedItems.end(); ++align_it )
00711 {
00712 QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *align_it, "", parentCommand );
00713 subcommand->savePreviousState();
00714 QTransform itemTransform = ( *align_it )->transform();
00715 itemTransform.translate( 0, maxYCoord - itemTransform.dy() - ( *align_it )->rect().height() );
00716 ( *align_it )->setTransform( itemTransform );
00717 subcommand->saveAfterState();
00718 }
00719 mUndoStack.push( parentCommand );
00720 }
00721
00722 void QgsComposition::updateZValues()
00723 {
00724 int counter = 1;
00725 QLinkedList<QgsComposerItem*>::iterator it = mItemZList.begin();
00726 QgsComposerItem* currentItem = 0;
00727
00728 QUndoCommand* parentCommand = new QUndoCommand( tr( "Item z-order changed" ) );
00729 for ( ; it != mItemZList.end(); ++it )
00730 {
00731 currentItem = *it;
00732 if ( currentItem )
00733 {
00734 QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *it, "", parentCommand );
00735 subcommand->savePreviousState();
00736 currentItem->setZValue( counter );
00737 subcommand->saveAfterState();
00738 }
00739 ++counter;
00740 }
00741 mUndoStack.push( parentCommand );
00742 }
00743
00744 void QgsComposition::sortZList()
00745 {
00746 if ( mItemZList.size() < 2 )
00747 {
00748 return;
00749 }
00750
00751 QLinkedList<QgsComposerItem*>::const_iterator lIt = mItemZList.constBegin();
00752 QLinkedList<QgsComposerItem*> sortedList;
00753
00754 for ( ; lIt != mItemZList.constEnd(); ++lIt )
00755 {
00756 QLinkedList<QgsComposerItem*>::iterator insertIt = sortedList.begin();
00757 for ( ; insertIt != sortedList.end(); ++insertIt )
00758 {
00759 if (( *lIt )->zValue() < ( *insertIt )->zValue() )
00760 {
00761 break;
00762 }
00763 }
00764 sortedList.insert( insertIt, ( *lIt ) );
00765 }
00766
00767 mItemZList = sortedList;
00768 }
00769
00770 QPointF QgsComposition::snapPointToGrid( const QPointF& scenePoint ) const
00771 {
00772 if ( !mSnapToGrid || mSnapGridResolution <= 0 )
00773 {
00774 return scenePoint;
00775 }
00776
00777
00778 int xRatio = ( int )(( scenePoint.x() - mSnapGridOffsetX ) / mSnapGridResolution + 0.5 );
00779 int yRatio = ( int )(( scenePoint.y() - mSnapGridOffsetY ) / mSnapGridResolution + 0.5 );
00780
00781 return QPointF( xRatio * mSnapGridResolution + mSnapGridOffsetX, yRatio * mSnapGridResolution + mSnapGridOffsetY );
00782 }
00783
00784 int QgsComposition::boundingRectOfSelectedItems( QRectF& bRect )
00785 {
00786 QList<QgsComposerItem*> selectedItems = selectedComposerItems();
00787 if ( selectedItems.size() < 1 )
00788 {
00789 return 1;
00790 }
00791
00792
00793 QgsComposerItem* currentItem = selectedItems.at( 0 );
00794 double minX = currentItem->transform().dx();
00795 double minY = currentItem->transform().dy();
00796 double maxX = minX + currentItem->rect().width();
00797 double maxY = minY + currentItem->rect().height();
00798
00799 double currentMinX, currentMinY, currentMaxX, currentMaxY;
00800
00801 for ( int i = 1; i < selectedItems.size(); ++i )
00802 {
00803 currentItem = selectedItems.at( i );
00804 currentMinX = currentItem->transform().dx();
00805 currentMinY = currentItem->transform().dy();
00806 currentMaxX = currentMinX + currentItem->rect().width();
00807 currentMaxY = currentMinY + currentItem->rect().height();
00808
00809 if ( currentMinX < minX )
00810 minX = currentMinX;
00811 if ( currentMaxX > maxX )
00812 maxX = currentMaxX;
00813 if ( currentMinY < minY )
00814 minY = currentMinY;
00815 if ( currentMaxY > maxY )
00816 maxY = currentMaxY;
00817 }
00818
00819 bRect.setTopLeft( QPointF( minX, minY ) );
00820 bRect.setBottomRight( QPointF( maxX, maxY ) );
00821 return 0;
00822 }
00823
00824 void QgsComposition::setSnapToGridEnabled( bool b )
00825 {
00826 mSnapToGrid = b;
00827 if ( mPaperItem )
00828 {
00829 mPaperItem->update();
00830 }
00831 saveSettings();
00832 }
00833
00834 void QgsComposition::setSnapGridResolution( double r )
00835 {
00836 mSnapGridResolution = r;
00837 if ( mPaperItem )
00838 {
00839 mPaperItem->update();
00840 }
00841 saveSettings();
00842 }
00843
00844 void QgsComposition::setSnapGridOffsetX( double offset )
00845 {
00846 mSnapGridOffsetX = offset;
00847 if ( mPaperItem )
00848 {
00849 mPaperItem->update();
00850 }
00851 saveSettings();
00852 }
00853
00854 void QgsComposition::setSnapGridOffsetY( double offset )
00855 {
00856 mSnapGridOffsetY = offset;
00857 if ( mPaperItem )
00858 {
00859 mPaperItem->update();
00860 }
00861 saveSettings();
00862 }
00863
00864 void QgsComposition::setGridPen( const QPen& p )
00865 {
00866 mGridPen = p;
00867 if ( mPaperItem )
00868 {
00869 mPaperItem->update();
00870 }
00871 saveSettings();
00872 }
00873
00874 void QgsComposition::setGridStyle( GridStyle s )
00875 {
00876 mGridStyle = s;
00877 if ( mPaperItem )
00878 {
00879 mPaperItem->update();
00880 }
00881 saveSettings();
00882 }
00883
00884 void QgsComposition::setSelectionTolerance( double tol )
00885 {
00886 mSelectionTolerance = tol;
00887 saveSettings();
00888 }
00889
00890 void QgsComposition::loadSettings()
00891 {
00892
00893 QSettings s;
00894
00895 QString gridStyleString;
00896 int red, green, blue;
00897 double penWidth;
00898
00899 gridStyleString = s.value( "/qgis/composerGridStyle", "Dots" ).toString();
00900 penWidth = s.value( "/qgis/composerGridWidth", 0.5 ).toDouble();
00901 red = s.value( "/qgis/composerGridRed", 0 ).toInt();
00902 green = s.value( "/qgis/composerGridGreen", 0 ).toInt();
00903 blue = s.value( "/qgis/composerGridBlue", 0 ).toInt();
00904
00905 mGridPen.setColor( QColor( red, green, blue ) );
00906 mGridPen.setWidthF( penWidth );
00907
00908 if ( gridStyleString == "Dots" )
00909 {
00910 mGridStyle = Dots;
00911 }
00912 else if ( gridStyleString == "Crosses" )
00913 {
00914 mGridStyle = Crosses;
00915 }
00916 else
00917 {
00918 mGridStyle = Solid;
00919 }
00920
00921 mSelectionTolerance = s.value( "/qgis/composerSelectionTolerance", 0.0 ).toDouble();
00922 }
00923
00924 void QgsComposition::saveSettings()
00925 {
00926
00927 QSettings s;
00928 s.setValue( "/qgis/composerGridWidth", mGridPen.widthF() );
00929 s.setValue( "/qgis/composerGridRed", mGridPen.color().red() );
00930 s.setValue( "/qgis/composerGridGreen", mGridPen.color().green() );
00931 s.setValue( "/qgis/composerGridBlue", mGridPen.color().blue() );
00932
00933 if ( mGridStyle == Solid )
00934 {
00935 s.setValue( "/qgis/composerGridStyle", "Solid" );
00936 }
00937 else if ( mGridStyle == Dots )
00938 {
00939 s.setValue( "/qgis/composerGridStyle", "Dots" );
00940 }
00941 else if ( mGridStyle == Crosses )
00942 {
00943 s.setValue( "/qgis/composerGridStyle", "Crosses" );
00944 }
00945
00946
00947 s.setValue( "/qgis/composerSelectionTolerance", mSelectionTolerance );
00948 }
00949
00950 void QgsComposition::beginCommand( QgsComposerItem* item, const QString& commandText, QgsComposerMergeCommand::Context c )
00951 {
00952 delete mActiveCommand;
00953 if ( !item )
00954 {
00955 mActiveCommand = 0;
00956 return;
00957 }
00958
00959 if ( c == QgsComposerMergeCommand::Unknown )
00960 {
00961 mActiveCommand = new QgsComposerItemCommand( item, commandText );
00962 }
00963 else
00964 {
00965 mActiveCommand = new QgsComposerMergeCommand( c, item, commandText );
00966 }
00967 mActiveCommand->savePreviousState();
00968 }
00969
00970 void QgsComposition::endCommand()
00971 {
00972 if ( mActiveCommand )
00973 {
00974 mActiveCommand->saveAfterState();
00975 if ( mActiveCommand->containsChange() )
00976 {
00977 mUndoStack.push( mActiveCommand );
00978 }
00979 else
00980 {
00981 delete mActiveCommand;
00982 }
00983 mActiveCommand = 0;
00984 }
00985 }
00986
00987 void QgsComposition::cancelCommand()
00988 {
00989 delete mActiveCommand;
00990 mActiveCommand = 0;
00991 }
00992
00993 void QgsComposition::addComposerArrow( QgsComposerArrow* arrow )
00994 {
00995 addItem( arrow );
00996 emit composerArrowAdded( arrow );
00997 clearSelection();
00998 arrow->setSelected( true );
00999 emit selectedItemChanged( arrow );
01000 }
01001
01002 void QgsComposition::addComposerLabel( QgsComposerLabel* label )
01003 {
01004 addItem( label );
01005 emit composerLabelAdded( label );
01006 clearSelection();
01007 label->setSelected( true );
01008 emit selectedItemChanged( label );
01009 }
01010
01011 void QgsComposition::addComposerMap( QgsComposerMap* map, bool setDefaultPreviewStyle )
01012 {
01013 addItem( map );
01014 if ( setDefaultPreviewStyle )
01015 {
01016
01017 map->setPreviewMode( QgsComposerMap::Cache );
01018 }
01019
01020 if ( map->previewMode() != QgsComposerMap::Rectangle )
01021 {
01022 map->cache();
01023 }
01024
01025 emit composerMapAdded( map );
01026 clearSelection();
01027 map->setSelected( true );
01028 emit selectedItemChanged( map );
01029 }
01030
01031 void QgsComposition::addComposerScaleBar( QgsComposerScaleBar* scaleBar )
01032 {
01033
01034 QList<const QgsComposerMap*> mapItemList = composerMapItems();
01035 if ( mapItemList.size() > 0 )
01036 {
01037 scaleBar->setComposerMap( mapItemList.at( 0 ) );
01038 }
01039 addItem( scaleBar );
01040 emit composerScaleBarAdded( scaleBar );
01041 clearSelection();
01042 scaleBar->setSelected( true );
01043 emit selectedItemChanged( scaleBar );
01044 }
01045
01046 void QgsComposition::addComposerLegend( QgsComposerLegend* legend )
01047 {
01048
01049 QList<const QgsComposerMap*> mapItemList = composerMapItems();
01050 if ( mapItemList.size() > 0 )
01051 {
01052 legend->setComposerMap( mapItemList.at( 0 ) );
01053 }
01054 addItem( legend );
01055 emit composerLegendAdded( legend );
01056 clearSelection();
01057 legend->setSelected( true );
01058 emit selectedItemChanged( legend );
01059 }
01060
01061 void QgsComposition::addComposerPicture( QgsComposerPicture* picture )
01062 {
01063 addItem( picture );
01064 emit composerPictureAdded( picture );
01065 clearSelection();
01066 picture->setSelected( true );
01067 emit selectedItemChanged( picture );
01068 }
01069
01070 void QgsComposition::addComposerShape( QgsComposerShape* shape )
01071 {
01072 addItem( shape );
01073 emit composerShapeAdded( shape );
01074 clearSelection();
01075 shape->setSelected( true );
01076 emit selectedItemChanged( shape );
01077 }
01078
01079 void QgsComposition::addComposerTable( QgsComposerAttributeTable* table )
01080 {
01081 addItem( table );
01082 emit composerTableAdded( table );
01083 clearSelection();
01084 table->setSelected( true );
01085 emit selectedItemChanged( table );
01086 }
01087
01088 void QgsComposition::removeComposerItem( QgsComposerItem* item )
01089 {
01090 QgsComposerMap* map = dynamic_cast<QgsComposerMap *>( item );
01091 if ( !map || !map->isDrawing() )
01092 {
01093 removeItem( item );
01094 QgsComposerItemGroup* itemGroup = dynamic_cast<QgsComposerItemGroup*>( item );
01095 if ( itemGroup )
01096 {
01097
01098 QUndoCommand* parentCommand = new QUndoCommand( tr( "Remove item group" ) );
01099
01100 QSet<QgsComposerItem*> groupedItems = itemGroup->items();
01101 QSet<QgsComposerItem*>::iterator it = groupedItems.begin();
01102 for ( ; it != groupedItems.end(); ++it )
01103 {
01104 QgsAddRemoveItemCommand* subcommand = new QgsAddRemoveItemCommand( QgsAddRemoveItemCommand::Removed, *it, this, "", parentCommand );
01105 connectAddRemoveCommandSignals( subcommand );
01106 emit itemRemoved( *it );
01107 }
01108
01109 undoStack()->push( parentCommand );
01110 delete itemGroup;
01111 emit itemRemoved( itemGroup );
01112 }
01113 else
01114 {
01115 emit itemRemoved( item );
01116 pushAddRemoveCommand( item, tr( "Item deleted" ), QgsAddRemoveItemCommand::Removed );
01117 }
01118 }
01119 }
01120
01121 void QgsComposition::pushAddRemoveCommand( QgsComposerItem* item, const QString& text, QgsAddRemoveItemCommand::State state )
01122 {
01123 QgsAddRemoveItemCommand* c = new QgsAddRemoveItemCommand( state, item, this, text );
01124 connectAddRemoveCommandSignals( c );
01125 undoStack()->push( c );
01126 }
01127
01128 void QgsComposition::connectAddRemoveCommandSignals( QgsAddRemoveItemCommand* c )
01129 {
01130 if ( !c )
01131 {
01132 return;
01133 }
01134
01135 QObject::connect( c, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SIGNAL( itemRemoved( QgsComposerItem* ) ) );
01136 QObject::connect( c, SIGNAL( itemAdded( QgsComposerItem* ) ), this, SLOT( sendItemAddedSignal( QgsComposerItem* ) ) );
01137 }
01138
01139 void QgsComposition::sendItemAddedSignal( QgsComposerItem* item )
01140 {
01141
01142 item->setSelected( true );
01143 QgsComposerArrow* arrow = dynamic_cast<QgsComposerArrow*>( item );
01144 if ( arrow )
01145 {
01146 emit composerArrowAdded( arrow );
01147 emit selectedItemChanged( arrow );
01148 return;
01149 }
01150 QgsComposerLabel* label = dynamic_cast<QgsComposerLabel*>( item );
01151 if ( label )
01152 {
01153 emit composerLabelAdded( label );
01154 emit selectedItemChanged( label );
01155 return;
01156 }
01157 QgsComposerMap* map = dynamic_cast<QgsComposerMap*>( item );
01158 if ( map )
01159 {
01160 emit composerMapAdded( map );
01161 emit selectedItemChanged( map );
01162 return;
01163 }
01164 QgsComposerScaleBar* scalebar = dynamic_cast<QgsComposerScaleBar*>( item );
01165 if ( scalebar )
01166 {
01167 emit composerScaleBarAdded( scalebar );
01168 emit selectedItemChanged( scalebar );
01169 return;
01170 }
01171 QgsComposerLegend* legend = dynamic_cast<QgsComposerLegend*>( item );
01172 if ( legend )
01173 {
01174 emit composerLegendAdded( legend );
01175 emit selectedItemChanged( legend );
01176 return;
01177 }
01178 QgsComposerPicture* picture = dynamic_cast<QgsComposerPicture*>( item );
01179 if ( picture )
01180 {
01181 emit composerPictureAdded( picture );
01182 emit selectedItemChanged( picture );
01183 return;
01184 }
01185 QgsComposerShape* shape = dynamic_cast<QgsComposerShape*>( item );
01186 if ( shape )
01187 {
01188 emit composerShapeAdded( shape );
01189 emit selectedItemChanged( shape );
01190 return;
01191 }
01192 QgsComposerAttributeTable* table = dynamic_cast<QgsComposerAttributeTable*>( item );
01193 if ( table )
01194 {
01195 emit composerTableAdded( table );
01196 emit selectedItemChanged( table );
01197 return;
01198 }
01199 }