Quantum GIS API Documentation
1.8
|
00001 /*************************************************************************** 00002 qgscomposerview.cpp 00003 ------------------- 00004 begin : January 2005 00005 copyright : (C) 2005 by Radim Blazek 00006 email : [email protected] 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include <QApplication> 00019 #include <QMainWindow> 00020 #include <QMouseEvent> 00021 #include <QKeyEvent> 00022 #include <QClipboard> 00023 #include <QMimeData> 00024 00025 #include "qgscomposerview.h" 00026 #include "qgscomposerarrow.h" 00027 #include "qgscomposerlabel.h" 00028 #include "qgscomposerlegend.h" 00029 #include "qgscomposermap.h" 00030 #include "qgscomposeritemgroup.h" 00031 #include "qgscomposerpicture.h" 00032 #include "qgscomposerscalebar.h" 00033 #include "qgscomposershape.h" 00034 #include "qgscomposerattributetable.h" 00035 #include "qgslogger.h" 00036 00037 QgsComposerView::QgsComposerView( QWidget* parent, const char* name, Qt::WFlags f ) 00038 : QGraphicsView( parent ) 00039 , mShiftKeyPressed( false ) 00040 , mRubberBandItem( 0 ) 00041 , mRubberBandLineItem( 0 ) 00042 , mMoveContentItem( 0 ) 00043 , mPaintingEnabled( true ) 00044 { 00045 Q_UNUSED( f ); 00046 Q_UNUSED( name ); 00047 00048 setResizeAnchor( QGraphicsView::AnchorViewCenter ); 00049 setMouseTracking( true ); 00050 viewport()->setMouseTracking( true ); 00051 } 00052 00053 void QgsComposerView::mousePressEvent( QMouseEvent* e ) 00054 { 00055 if ( !composition() ) 00056 { 00057 return; 00058 } 00059 00060 QPointF scenePoint = mapToScene( e->pos() ); 00061 QPointF snappedScenePoint = composition()->snapPointToGrid( scenePoint ); 00062 00063 //lock/unlock position of item with right click 00064 if ( e->button() == Qt::RightButton ) 00065 { 00066 QgsComposerItem* selectedItem = composition()->composerItemAt( scenePoint ); 00067 if ( selectedItem ) 00068 { 00069 bool lock = selectedItem->positionLock() ? false : true; 00070 selectedItem->setPositionLock( lock ); 00071 selectedItem->update(); 00072 //make sure the new cursor is correct 00073 QPointF itemPoint = selectedItem->mapFromScene( scenePoint ); 00074 selectedItem->updateCursor( itemPoint ); 00075 } 00076 return; 00077 } 00078 00079 switch ( mCurrentTool ) 00080 { 00081 //select/deselect items and pass mouse event further 00082 case Select: 00083 { 00084 if ( !mShiftKeyPressed ) //keep selection if shift key pressed 00085 { 00086 composition()->clearSelection(); 00087 } 00088 00089 //select topmost item at position of event 00090 QgsComposerItem* selectedItem = composition()->composerItemAt( scenePoint ); 00091 if ( !selectedItem ) 00092 { 00093 break; 00094 } 00095 00096 selectedItem->setSelected( true ); 00097 QGraphicsView::mousePressEvent( e ); 00098 emit selectedItemChanged( selectedItem ); 00099 break; 00100 } 00101 00102 case MoveItemContent: 00103 { 00104 //store item as member if it is selected and cursor is over item 00105 QgsComposerItem* item = dynamic_cast<QgsComposerItem *>( itemAt( e->pos() ) ); 00106 if ( item ) 00107 { 00108 mMoveContentStartPos = scenePoint; 00109 } 00110 mMoveContentItem = item; 00111 break; 00112 } 00113 00114 case AddArrow: 00115 { 00116 mRubberBandStartPos = QPointF( snappedScenePoint.x(), snappedScenePoint.y() ); 00117 mRubberBandLineItem = new QGraphicsLineItem( snappedScenePoint.x(), snappedScenePoint.y(), snappedScenePoint.x(), snappedScenePoint.y() ); 00118 mRubberBandLineItem->setZValue( 100 ); 00119 scene()->addItem( mRubberBandLineItem ); 00120 scene()->update(); 00121 break; 00122 } 00123 00124 //create rubber band for map and ellipse items 00125 case AddMap: 00126 case AddRectangle: 00127 case AddTriangle: 00128 case AddEllipse: 00129 { 00130 QTransform t; 00131 mRubberBandItem = new QGraphicsRectItem( 0, 0, 0, 0 ); 00132 mRubberBandStartPos = QPointF( snappedScenePoint.x(), snappedScenePoint.y() ); 00133 t.translate( snappedScenePoint.x(), snappedScenePoint.y() ); 00134 mRubberBandItem->setTransform( t ); 00135 mRubberBandItem->setZValue( 100 ); 00136 scene()->addItem( mRubberBandItem ); 00137 scene()->update(); 00138 } 00139 break; 00140 00141 case AddLabel: 00142 if ( composition() ) 00143 { 00144 QgsComposerLabel* newLabelItem = new QgsComposerLabel( composition() ); 00145 newLabelItem->setText( tr( "Quantum GIS" ) ); 00146 newLabelItem->adjustSizeToText(); 00147 newLabelItem->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), newLabelItem->rect().width(), newLabelItem->rect().height() ) ); 00148 composition()->addComposerLabel( newLabelItem ); 00149 emit actionFinished(); 00150 composition()->pushAddRemoveCommand( newLabelItem, tr( "Label added" ) ); 00151 } 00152 break; 00153 00154 case AddScalebar: 00155 if ( composition() ) 00156 { 00157 QgsComposerScaleBar* newScaleBar = new QgsComposerScaleBar( composition() ); 00158 newScaleBar->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 20, 20 ) ); 00159 composition()->addComposerScaleBar( newScaleBar ); 00160 QList<const QgsComposerMap*> mapItemList = composition()->composerMapItems(); 00161 if ( mapItemList.size() > 0 ) 00162 { 00163 newScaleBar->setComposerMap( mapItemList.at( 0 ) ); 00164 } 00165 newScaleBar->applyDefaultSize(); //4 segments, 1/5 of composer map width 00166 emit actionFinished(); 00167 composition()->pushAddRemoveCommand( newScaleBar, tr( "Scale bar added" ) ); 00168 } 00169 break; 00170 00171 case AddLegend: 00172 { 00173 if ( composition() ) 00174 { 00175 QgsComposerLegend* newLegend = new QgsComposerLegend( composition() ); 00176 newLegend->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), newLegend->rect().width(), newLegend->rect().height() ) ); 00177 composition()->addComposerLegend( newLegend ); 00178 newLegend->updateLegend(); 00179 emit actionFinished(); 00180 composition()->pushAddRemoveCommand( newLegend, tr( "Legend added" ) ); 00181 } 00182 break; 00183 } 00184 case AddPicture: 00185 if ( composition() ) 00186 { 00187 QgsComposerPicture* newPicture = new QgsComposerPicture( composition() ); 00188 newPicture->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 30, 30 ) ); 00189 composition()->addComposerPicture( newPicture ); 00190 emit actionFinished(); 00191 composition()->pushAddRemoveCommand( newPicture, tr( "Picture added" ) ); 00192 } 00193 break; 00194 case AddTable: 00195 if ( composition() ) 00196 { 00197 QgsComposerAttributeTable* newTable = new QgsComposerAttributeTable( composition() ); 00198 newTable->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 50, 50 ) ); 00199 composition()->addComposerTable( newTable ); 00200 emit actionFinished(); 00201 composition()->pushAddRemoveCommand( newTable, tr( "Table added" ) ); 00202 } 00203 break; 00204 default: 00205 break; 00206 } 00207 } 00208 00209 void QgsComposerView::addShape( Tool currentTool ) 00210 { 00211 QgsComposerShape::Shape shape = QgsComposerShape::Ellipse; 00212 00213 if ( currentTool == AddRectangle ) 00214 shape = QgsComposerShape::Rectangle; 00215 else if ( currentTool == AddTriangle ) 00216 shape = QgsComposerShape::Triangle; 00217 00218 if ( !mRubberBandItem || mRubberBandItem->rect().width() < 0.1 || mRubberBandItem->rect().width() < 0.1 ) 00219 { 00220 scene()->removeItem( mRubberBandItem ); 00221 delete mRubberBandItem; 00222 mRubberBandItem = 0; 00223 return; 00224 } 00225 if ( composition() ) 00226 { 00227 QgsComposerShape* composerShape = new QgsComposerShape( mRubberBandItem->transform().dx(), mRubberBandItem->transform().dy(), mRubberBandItem->rect().width(), mRubberBandItem->rect().height(), composition() ); 00228 composerShape->setShapeType( shape ); 00229 composition()->addComposerShape( composerShape ); 00230 scene()->removeItem( mRubberBandItem ); 00231 delete mRubberBandItem; 00232 mRubberBandItem = 0; 00233 emit actionFinished(); 00234 composition()->pushAddRemoveCommand( composerShape, tr( "Shape added" ) ); 00235 } 00236 } 00237 00238 void QgsComposerView::mouseReleaseEvent( QMouseEvent* e ) 00239 { 00240 if ( !composition() ) 00241 { 00242 return; 00243 } 00244 00245 QPointF scenePoint = mapToScene( e->pos() ); 00246 00247 switch ( mCurrentTool ) 00248 { 00249 case Select: 00250 { 00251 QGraphicsView::mouseReleaseEvent( e ); 00252 break; 00253 } 00254 00255 case MoveItemContent: 00256 { 00257 if ( mMoveContentItem ) 00258 { 00259 //update map preview if composer map 00260 QgsComposerMap* composerMap = dynamic_cast<QgsComposerMap *>( mMoveContentItem ); 00261 if ( composerMap ) 00262 { 00263 composerMap->setOffset( 0, 0 ); 00264 } 00265 00266 double moveX = scenePoint.x() - mMoveContentStartPos.x(); 00267 double moveY = scenePoint.y() - mMoveContentStartPos.y(); 00268 00269 composition()->beginCommand( mMoveContentItem, tr( "Move item content" ) ); 00270 mMoveContentItem->moveContent( -moveX, -moveY ); 00271 composition()->endCommand(); 00272 mMoveContentItem = 0; 00273 } 00274 break; 00275 } 00276 case AddArrow: 00277 if ( composition() ) 00278 { 00279 QPointF scenePoint = mapToScene( e->pos() ); 00280 QPointF snappedScenePoint = composition()->snapPointToGrid( scenePoint ); 00281 QgsComposerArrow* composerArrow = new QgsComposerArrow( mRubberBandStartPos, QPointF( snappedScenePoint.x(), snappedScenePoint.y() ), composition() ); 00282 composition()->addComposerArrow( composerArrow ); 00283 scene()->removeItem( mRubberBandLineItem ); 00284 delete mRubberBandLineItem; 00285 mRubberBandLineItem = 0; 00286 emit actionFinished(); 00287 composition()->pushAddRemoveCommand( composerArrow, tr( "Arrow added" ) ); 00288 } 00289 break; 00290 00291 case AddRectangle: 00292 case AddTriangle: 00293 case AddEllipse: 00294 addShape( mCurrentTool ); 00295 break; 00296 00297 case AddMap: 00298 if ( !mRubberBandItem || mRubberBandItem->rect().width() < 0.1 || mRubberBandItem->rect().width() < 0.1 ) 00299 { 00300 if ( mRubberBandItem ) 00301 { 00302 scene()->removeItem( mRubberBandItem ); 00303 delete mRubberBandItem; 00304 mRubberBandItem = 0; 00305 } 00306 return; 00307 } 00308 if ( composition() ) 00309 { 00310 QgsComposerMap* composerMap = new QgsComposerMap( composition(), mRubberBandItem->transform().dx(), mRubberBandItem->transform().dy(), mRubberBandItem->rect().width(), mRubberBandItem->rect().height() ); 00311 composition()->addComposerMap( composerMap ); 00312 scene()->removeItem( mRubberBandItem ); 00313 delete mRubberBandItem; 00314 mRubberBandItem = 0; 00315 emit actionFinished(); 00316 composition()->pushAddRemoveCommand( composerMap, tr( "Map added" ) ); 00317 } 00318 break; 00319 00320 default: 00321 break; 00322 } 00323 } 00324 00325 void QgsComposerView::mouseMoveEvent( QMouseEvent* e ) 00326 { 00327 if ( !composition() ) 00328 { 00329 return; 00330 } 00331 00332 if ( e->buttons() == Qt::NoButton ) 00333 { 00334 if ( mCurrentTool == Select ) 00335 { 00336 QGraphicsView::mouseMoveEvent( e ); 00337 } 00338 } 00339 else 00340 { 00341 QPointF scenePoint = mapToScene( e->pos() ); 00342 00343 switch ( mCurrentTool ) 00344 { 00345 case Select: 00346 QGraphicsView::mouseMoveEvent( e ); 00347 break; 00348 00349 case AddArrow: 00350 { 00351 if ( mRubberBandLineItem ) 00352 { 00353 mRubberBandLineItem->setLine( mRubberBandStartPos.x(), mRubberBandStartPos.y(), scenePoint.x(), scenePoint.y() ); 00354 } 00355 break; 00356 } 00357 00358 case AddMap: 00359 case AddRectangle: 00360 case AddTriangle: 00361 case AddEllipse: 00362 //adjust rubber band item 00363 { 00364 double x = 0; 00365 double y = 0; 00366 double width = 0; 00367 double height = 0; 00368 00369 double dx = scenePoint.x() - mRubberBandStartPos.x(); 00370 double dy = scenePoint.y() - mRubberBandStartPos.y(); 00371 00372 if ( dx < 0 ) 00373 { 00374 x = scenePoint.x(); 00375 width = -dx; 00376 } 00377 else 00378 { 00379 x = mRubberBandStartPos.x(); 00380 width = dx; 00381 } 00382 00383 if ( dy < 0 ) 00384 { 00385 y = scenePoint.y(); 00386 height = -dy; 00387 } 00388 else 00389 { 00390 y = mRubberBandStartPos.y(); 00391 height = dy; 00392 } 00393 00394 if ( mRubberBandItem ) 00395 { 00396 mRubberBandItem->setRect( 0, 0, width, height ); 00397 QTransform t; 00398 t.translate( x, y ); 00399 mRubberBandItem->setTransform( t ); 00400 } 00401 break; 00402 } 00403 00404 case MoveItemContent: 00405 { 00406 //update map preview if composer map 00407 QgsComposerMap* composerMap = dynamic_cast<QgsComposerMap *>( mMoveContentItem ); 00408 if ( composerMap ) 00409 { 00410 composerMap->setOffset( scenePoint.x() - mMoveContentStartPos.x(), scenePoint.y() - mMoveContentStartPos.y() ); 00411 composerMap->update(); 00412 } 00413 break; 00414 } 00415 default: 00416 break; 00417 } 00418 } 00419 } 00420 00421 void QgsComposerView::mouseDoubleClickEvent( QMouseEvent* e ) 00422 { 00423 e->ignore(); 00424 } 00425 00426 void QgsComposerView::keyPressEvent( QKeyEvent * e ) 00427 { 00428 if ( e->key() == Qt::Key_Shift ) 00429 { 00430 mShiftKeyPressed = true; 00431 } 00432 00433 if ( !composition() ) 00434 { 00435 return; 00436 } 00437 00438 QList<QgsComposerItem*> composerItemList = composition()->selectedComposerItems(); 00439 QList<QgsComposerItem*>::iterator itemIt = composerItemList.begin(); 00440 00441 if ( e->matches( QKeySequence::Copy ) || e->matches( QKeySequence::Cut ) ) 00442 { 00443 QDomDocument doc; 00444 QDomElement documentElement = doc.createElement( "ComposerItemClipboard" ); 00445 for ( ; itemIt != composerItemList.end(); ++itemIt ) 00446 { 00447 // copy each item in a group 00448 QgsComposerItemGroup* itemGroup = dynamic_cast<QgsComposerItemGroup*>( *itemIt ); 00449 if ( itemGroup && composition() ) 00450 { 00451 QSet<QgsComposerItem*> groupedItems = itemGroup->items(); 00452 QSet<QgsComposerItem*>::iterator it = groupedItems.begin(); 00453 for ( ; it != groupedItems.end(); ++it ) 00454 { 00455 ( *it )->writeXML( documentElement, doc ); 00456 } 00457 } 00458 ( *itemIt )->writeXML( documentElement, doc ); 00459 if ( e->matches( QKeySequence::Cut ) ) 00460 { 00461 composition()->removeComposerItem( *itemIt ); 00462 } 00463 } 00464 doc.appendChild( documentElement ); 00465 QMimeData *mimeData = new QMimeData; 00466 mimeData->setData( "text/xml", doc.toByteArray() ); 00467 QClipboard *clipboard = QApplication::clipboard(); 00468 clipboard->setMimeData( mimeData ); 00469 } 00470 00471 if ( e->matches( QKeySequence::Paste ) ) 00472 { 00473 QDomDocument doc; 00474 QClipboard *clipboard = QApplication::clipboard(); 00475 if ( doc.setContent( clipboard->mimeData()->data( "text/xml" ) ) ) 00476 { 00477 QDomElement docElem = doc.documentElement(); 00478 if ( docElem.tagName() == "ComposerItemClipboard" ) 00479 { 00480 if ( composition() ) 00481 { 00482 QPointF pt = mapToScene( mapFromGlobal( QCursor::pos() ) ); 00483 composition()->addItemsFromXML( docElem, doc, 0, true, &pt ); 00484 } 00485 } 00486 } 00487 } 00488 00489 //delete selected items 00490 if ( e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace ) 00491 { 00492 for ( ; itemIt != composerItemList.end(); ++itemIt ) 00493 { 00494 if ( composition() ) 00495 { 00496 composition()->removeComposerItem( *itemIt ); 00497 } 00498 } 00499 } 00500 00501 else if ( e->key() == Qt::Key_Left ) 00502 { 00503 for ( ; itemIt != composerItemList.end(); ++itemIt ) 00504 { 00505 ( *itemIt )->move( -1.0, 0.0 ); 00506 } 00507 } 00508 else if ( e->key() == Qt::Key_Right ) 00509 { 00510 for ( ; itemIt != composerItemList.end(); ++itemIt ) 00511 { 00512 ( *itemIt )->move( 1.0, 0.0 ); 00513 } 00514 } 00515 else if ( e->key() == Qt::Key_Down ) 00516 { 00517 for ( ; itemIt != composerItemList.end(); ++itemIt ) 00518 { 00519 ( *itemIt )->move( 0.0, 1.0 ); 00520 } 00521 } 00522 else if ( e->key() == Qt::Key_Up ) 00523 { 00524 for ( ; itemIt != composerItemList.end(); ++itemIt ) 00525 { 00526 ( *itemIt )->move( 0.0, -1.0 ); 00527 } 00528 } 00529 } 00530 00531 void QgsComposerView::keyReleaseEvent( QKeyEvent * e ) 00532 { 00533 if ( e->key() == Qt::Key_Shift ) 00534 { 00535 mShiftKeyPressed = false; 00536 } 00537 } 00538 00539 void QgsComposerView::wheelEvent( QWheelEvent* event ) 00540 { 00541 QPointF scenePoint = mapToScene( event->pos() ); 00542 00543 //select topmost item at position of event 00544 QgsComposerItem* theItem = composition()->composerItemAt( scenePoint ); 00545 if ( theItem ) 00546 { 00547 if ( theItem->isSelected() ) 00548 { 00549 QPointF itemPoint = theItem->mapFromScene( scenePoint ); 00550 theItem->beginCommand( tr( "Zoom item content" ) ); 00551 theItem->zoomContent( event->delta(), itemPoint.x(), itemPoint.y() ); 00552 theItem->endCommand(); 00553 } 00554 } 00555 } 00556 00557 void QgsComposerView::paintEvent( QPaintEvent* event ) 00558 { 00559 if ( mPaintingEnabled ) 00560 { 00561 QGraphicsView::paintEvent( event ); 00562 event->accept(); 00563 } 00564 else 00565 { 00566 event->ignore(); 00567 } 00568 } 00569 00570 void QgsComposerView::hideEvent( QHideEvent* e ) 00571 { 00572 emit( composerViewHide( this ) ); 00573 e->ignore(); 00574 } 00575 00576 void QgsComposerView::showEvent( QShowEvent* e ) 00577 { 00578 emit( composerViewShow( this ) ); 00579 e->ignore(); 00580 } 00581 00582 void QgsComposerView::setComposition( QgsComposition* c ) 00583 { 00584 setScene( c ); 00585 } 00586 00587 QgsComposition* QgsComposerView::composition() 00588 { 00589 if ( scene() ) 00590 { 00591 QgsComposition* c = dynamic_cast<QgsComposition *>( scene() ); 00592 if ( c ) 00593 { 00594 return c; 00595 } 00596 } 00597 return 0; 00598 } 00599 00600 void QgsComposerView::groupItems() 00601 { 00602 if ( !composition() ) 00603 { 00604 return; 00605 } 00606 00607 QList<QgsComposerItem*> selectionList = composition()->selectedComposerItems(); 00608 if ( selectionList.size() < 2 ) 00609 { 00610 return; //not enough items for a group 00611 } 00612 QgsComposerItemGroup* itemGroup = new QgsComposerItemGroup( composition() ); 00613 00614 QList<QgsComposerItem*>::iterator itemIter = selectionList.begin(); 00615 for ( ; itemIter != selectionList.end(); ++itemIter ) 00616 { 00617 itemGroup->addItem( *itemIter ); 00618 } 00619 00620 composition()->addItem( itemGroup ); 00621 itemGroup->setSelected( true ); 00622 emit selectedItemChanged( itemGroup ); 00623 } 00624 00625 void QgsComposerView::ungroupItems() 00626 { 00627 if ( !composition() ) 00628 { 00629 return; 00630 } 00631 00632 QList<QgsComposerItem*> selectionList = composition()->selectedComposerItems(); 00633 QList<QgsComposerItem*>::iterator itemIter = selectionList.begin(); 00634 for ( ; itemIter != selectionList.end(); ++itemIter ) 00635 { 00636 QgsComposerItemGroup* itemGroup = dynamic_cast<QgsComposerItemGroup *>( *itemIter ); 00637 if ( itemGroup ) 00638 { 00639 itemGroup->removeItems(); 00640 composition()->removeItem( *itemIter ); 00641 delete( *itemIter ); 00642 emit itemRemoved( *itemIter ); 00643 } 00644 } 00645 } 00646 00647 QMainWindow* QgsComposerView::composerWindow() 00648 { 00649 QMainWindow* composerObject = 0; 00650 QObject* currentObject = parent(); 00651 if ( !currentObject ) 00652 { 00653 return qobject_cast<QMainWindow *>( currentObject ); 00654 } 00655 00656 while ( true ) 00657 { 00658 composerObject = qobject_cast<QMainWindow*>( currentObject ); 00659 if ( composerObject || currentObject->parent() == 0 ) 00660 { 00661 return composerObject; 00662 } 00663 currentObject = currentObject->parent(); 00664 } 00665 00666 return 0; 00667 }