1 // Copyright (C) 2013-2015 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "GraphicsView_ViewPort.h"
22 #include "GraphicsView_Object.h"
23 #include "GraphicsView_Scene.h"
24 #include "GraphicsView_ViewTransformer.h"
26 #include "SUIT_ResourceMgr.h"
27 #include "SUIT_Session.h"
30 #include <QGraphicsSceneMouseEvent>
31 #include <QGridLayout>
35 #include <QRubberBand>
40 #define FOREGROUND_Z_VALUE -2
41 #define GRID_Z_VALUE -1
42 #define SKETCH_Z_VALUE 3000
44 int GraphicsView_ViewPort::nCounter = 0;
45 QCursor* GraphicsView_ViewPort::defCursor = 0;
46 QCursor* GraphicsView_ViewPort::handCursor = 0;
47 QCursor* GraphicsView_ViewPort::panCursor = 0;
48 QCursor* GraphicsView_ViewPort::panglCursor = 0;
49 QCursor* GraphicsView_ViewPort::zoomCursor = 0;
50 QCursor* GraphicsView_ViewPort::sketchCursor = 0;
52 //=======================================================================
53 // Name : GraphicsView_ViewPort::ViewLabel
54 // Purpose : Wrapper for label, which can ignore move events sent from
55 // QGraphicsView::scrollContentsBy() method, which,
56 // in its turn, called from GraphicsView_ViewPort::pan()
57 //=======================================================================
58 class GraphicsView_ViewPort::ViewLabel : public QLabel
61 ViewLabel( QWidget* theParent )
62 : QLabel( theParent ),
63 myAcceptMoveEvents( false )
68 void setAcceptMoveEvents( bool theFlag )
70 myAcceptMoveEvents = theFlag;
74 virtual void moveEvent( QMoveEvent* theEvent )
76 if( myAcceptMoveEvents )
77 QLabel::moveEvent( theEvent );
78 else // return the label to the initial position
80 myAcceptMoveEvents = true;
81 move( theEvent->oldPos() );
82 myAcceptMoveEvents = false;
87 bool myAcceptMoveEvents;
90 //================================================================
91 // Function : createCursors
93 //================================================================
94 void GraphicsView_ViewPort::createCursors ()
96 defCursor = new QCursor( Qt::ArrowCursor );
97 handCursor = new QCursor( Qt::PointingHandCursor );
98 panCursor = new QCursor( Qt::SizeAllCursor );
99 panglCursor = new QCursor( Qt::CrossCursor );
101 SUIT_ResourceMgr* rmgr = SUIT_Session::session()->resourceMgr();
102 zoomCursor = new QCursor( rmgr->loadPixmap( "GraphicsView", tr( "ICON_GV_CURSOR_ZOOM" ) ) );
104 sketchCursor = new QCursor( Qt::CrossCursor );
107 //================================================================
108 // Function : destroyCursors
110 //================================================================
111 void GraphicsView_ViewPort::destroyCursors()
113 delete defCursor; defCursor = 0;
114 delete handCursor; handCursor = 0;
115 delete panCursor; panCursor = 0;
116 delete panglCursor; panglCursor = 0;
117 delete zoomCursor; zoomCursor = 0;
118 delete sketchCursor; sketchCursor = 0;
121 //=======================================================================
122 // Name : GraphicsView_ViewPort
123 // Purpose : Constructor
124 //=======================================================================
125 GraphicsView_ViewPort::GraphicsView_ViewPort( QWidget* theParent )
126 : QGraphicsView( theParent ),
127 myInteractionFlags( 0 ),
129 myViewLabelPosition( VLP_None ),
130 myViewLabelLayout( 0 ),
131 myIsMousePositionEnabled( false ),
132 myForegroundItem( 0 ),
134 myIsTransforming( false ),
135 myHighlightedObject( 0 ),
138 myIsHighlighting( false ),
139 mySelectionIterator( 0 ),
141 myAreSelectionPointsInitialized( false ),
142 mySketchingItem( 0 ),
143 myIsPrepareToSketch( false ),
144 myIsSketching( false ),
145 myIsSketchingByPath( false ),
146 myIsDragging( false ),
147 myIsDragPositionInitialized( false ),
148 myIsPulling( false ),
149 myPullingObject( 0 ),
150 myStoredCursor( Qt::ArrowCursor )
153 myScene = new GraphicsView_Scene( this );
160 setInteractionFlags( EditFlags );
161 //setInteractionFlag( TraceBoundingRect );
162 //setInteractionFlag( DraggingByMiddleButton );
163 //setInteractionFlag( ImmediateContextMenu );
164 //setInteractionFlag( ImmediateSelection );
165 //setInteractionFlag( Sketching );
168 setBackgroundBrush( QBrush( Qt::white ) );
171 myIsForegroundEnabled = false;
172 myForegroundSize = QSizeF( 100, 30 );
173 myForegroundMargin = 0.0;
174 myForegroundColor = Qt::white;
175 myForegroundFrameColor = Qt::black;
176 myForegroundFrameLineWidth = 1.0;
179 myIsGridEnabled = false;
180 myGridCellSize = 100;
181 myGridLineStyle = Qt::DotLine;
182 myGridLineColor = Qt::darkGray;
184 // default index method (BspTreeIndex) leads to
185 // crashes in QGraphicsView::paintEvent() method
186 myScene->setItemIndexMethod( QGraphicsScene::NoIndex );
188 // render hints (default - TextAntialiasing only)
189 setRenderHints( QPainter::Antialiasing |
190 QPainter::TextAntialiasing |
191 QPainter::SmoothPixmapTransform |
192 QPainter::HighQualityAntialiasing );
194 connect( myScene, SIGNAL( gsKeyEvent( QKeyEvent* ) ),
195 this, SLOT( onKeyEvent( QKeyEvent* ) ) );
196 connect( myScene, SIGNAL( gsMouseEvent( QGraphicsSceneMouseEvent* ) ),
197 this, SLOT( onMouseEvent( QGraphicsSceneMouseEvent* ) ) );
198 connect( myScene, SIGNAL( gsWheelEvent( QGraphicsSceneWheelEvent* ) ),
199 this, SLOT( onWheelEvent( QGraphicsSceneWheelEvent* ) ) );
200 connect( myScene, SIGNAL( gsContextMenuEvent( QGraphicsSceneContextMenuEvent* ) ),
201 this, SLOT( onContextMenuEvent( QGraphicsSceneContextMenuEvent* ) ) );
203 connect( myScene, SIGNAL( gsBoundingRectChanged() ),
204 this, SLOT( onBoundingRectChanged() ) );
209 //=======================================================================
210 // Name : GraphicsView_ViewPort
211 // Purpose : Destructor
212 //=======================================================================
213 GraphicsView_ViewPort::~GraphicsView_ViewPort()
224 //================================================================
225 // Function : initialize
227 //================================================================
228 void GraphicsView_ViewPort::initialize()
230 if ( nCounter++ == 0 )
233 setMouseTracking( true );
234 setFocusPolicy( Qt::StrongFocus );
237 //================================================================
238 // Function : cleanup
240 //================================================================
241 void GraphicsView_ViewPort::cleanup()
243 if ( --nCounter == 0 )
247 //================================================================
248 // Function : addItem
250 //================================================================
251 void GraphicsView_ViewPort::addItem( QGraphicsItem* theItem )
253 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( theItem ) )
255 int aPriority = anObject->getPriority();
256 GraphicsView_ObjectList::iterator anIter, anIterEnd = myObjects.end();
257 for( anIter = myObjects.begin(); anIter != anIterEnd; anIter++ )
259 if( GraphicsView_Object* anObjectRef = *anIter )
261 if( anObjectRef->getPriority() > aPriority )
265 myObjects.insert( anIter, anObject );
266 anObject->setViewTransform( transform() );
267 anObject->addTo( this );
270 myScene->addItem( theItem );
271 onBoundingRectChanged();
274 //================================================================
275 // Function : isItemAdded
277 //================================================================
278 bool GraphicsView_ViewPort::isItemAdded( QGraphicsItem* theItem )
280 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( theItem ) )
282 for( GraphicsView_ObjectList::iterator anIter = myObjects.begin(); anIter != myObjects.end(); anIter++ )
283 if( theItem == *anIter )
287 for( int i = 0; i < myScene->items().size(); i++ )
288 if( theItem == myScene->items().at(i) )
294 //================================================================
295 // Function : removeItem
297 //================================================================
298 void GraphicsView_ViewPort::removeItem( QGraphicsItem* theItem )
300 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( theItem ) )
302 if( myHighlightedObject == anObject )
303 myHighlightedObject = 0;
304 mySelectedObjects.removeAll( anObject );
305 myObjects.removeAll( anObject );
306 anObject->removeFrom( this );
309 myScene->removeItem( theItem );
310 onBoundingRectChanged();
313 //================================================================
314 // Function : getObjects
316 //================================================================
317 GraphicsView_ObjectList GraphicsView_ViewPort::getObjects( SortType theSortType ) const
319 if( theSortType == SelectedFirst )
321 // to append selected objects after their non-selected siblings with similar priority
322 int aCurrentPriority = -1;
323 GraphicsView_ObjectList aSelectedObjects;
324 GraphicsView_ObjectList aTopmostObjects;
326 GraphicsView_ObjectList aList;
327 GraphicsView_ObjectListIterator anIter( myObjects );
328 while( anIter.hasNext() )
330 if( GraphicsView_Object* anObject = anIter.next() )
332 if( anObject->isOnTop() )
334 aTopmostObjects.append( anObject );
338 int aPriority = anObject->getPriority();
339 if( aPriority > aCurrentPriority )
341 if( !aSelectedObjects.isEmpty() )
343 aList.append( aSelectedObjects );
344 aSelectedObjects.clear();
346 aCurrentPriority = aPriority;
349 if( anObject->isSelected() )
350 aSelectedObjects.append( anObject );
352 aList.append( anObject );
356 // for selected objects with highest priority,
357 // which were not pushed to the result list yet
358 if( !aSelectedObjects.isEmpty() )
360 aList.append( aSelectedObjects );
361 aSelectedObjects.clear();
364 aList.append( aTopmostObjects );
369 if( theSortType == SortByZLevel ) // double loop, needs to be optimized
371 GraphicsView_ObjectList aList;
373 GraphicsView_ObjectListIterator anIter( myObjects );
374 while( anIter.hasNext() )
376 if( GraphicsView_Object* anObject = anIter.next() )
378 double aZValue = anObject->zValue();
379 GraphicsView_ObjectList::iterator anIter1, anIter1End = aList.end();
380 for( anIter1 = aList.begin(); anIter1 != anIter1End; anIter1++ )
381 if( GraphicsView_Object* anObjectRef = *anIter1 )
382 if( anObjectRef->zValue() > aZValue )
384 aList.insert( anIter1, anObject );
390 return myObjects; // theSortType == NoSorting
393 //================================================================
394 // Function : objectsBoundingRect
396 //================================================================
397 QRectF GraphicsView_ViewPort::objectsBoundingRect( bool theOnlyVisible ) const
400 QListIterator<QGraphicsItem*> anIter( items() );
401 while( anIter.hasNext() )
403 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
405 if( theOnlyVisible && !anObject->isVisible() )
408 QRectF anObjectRect = anObject->getRect();
409 if( !anObjectRect.isNull() )
412 aRect = anObject->getRect();
414 aRect |= anObject->getRect();
421 //================================================================
422 // Function : dumpView
424 //================================================================
425 QImage GraphicsView_ViewPort::dumpView( bool theWholeScene,
428 if( !theWholeScene ) // just grab the view contents
430 QPixmap aPixmap = QPixmap::grabWindow( viewport()->winId() );
431 return aPixmap.toImage();
434 // get a bounding rect of all presented objects
435 // (itemsBoundingRect() method is unsuitable)
436 QRectF aRect = objectsBoundingRect();
440 QRectF aTargetRect( 0, 0, aRect.width(), aRect.height() );
441 if( theSize.isValid() )
443 double aRatioX = theSize.width() / aTargetRect.width();
444 double aRatioY = theSize.height() / aTargetRect.height();
445 double aRatio = qMin( aRatioX, aRatioY );
446 aTargetRect.setWidth( aTargetRect.width() * aRatio );
447 aTargetRect.setHeight( aTargetRect.height() * aRatio );
450 // render the scene to an image
451 QImage anImage( aTargetRect.toRect().size(), QImage::Format_RGB32 );
452 QPainter aPainter( &anImage );
453 aPainter.setRenderHints( renderHints() );
455 myScene->render( &aPainter, aTargetRect, aRect );
460 //================================================================
461 // Function : setSceneGap
463 //================================================================
464 void GraphicsView_ViewPort::setSceneGap( double theSceneGap )
466 mySceneGap = theSceneGap;
467 onBoundingRectChanged();
470 //================================================================
471 // Function : setFitAllGap
473 //================================================================
474 void GraphicsView_ViewPort::setFitAllGap( double theFitAllGap )
476 myFitAllGap = theFitAllGap;
479 //================================================================
480 // Function : interactionFlags
482 //================================================================
483 int GraphicsView_ViewPort::interactionFlags() const
485 return myInteractionFlags;
488 //================================================================
489 // Function : hasInteractionFlag
491 //================================================================
492 bool GraphicsView_ViewPort::hasInteractionFlag( InteractionFlag theFlag )
494 return ( interactionFlags() & theFlag ) == theFlag;
497 //================================================================
498 // Function : setInteractionFlag
500 //================================================================
501 void GraphicsView_ViewPort::setInteractionFlag( InteractionFlag theFlag,
505 setInteractionFlags( myInteractionFlags | theFlag );
507 setInteractionFlags( myInteractionFlags & ~theFlag );
510 //================================================================
511 // Function : setInteractionFlags
513 //================================================================
514 void GraphicsView_ViewPort::setInteractionFlags( InteractionFlags theFlags )
516 myInteractionFlags = theFlags;
519 //================================================================
520 // Function : setViewLabelPosition
522 //================================================================
523 void GraphicsView_ViewPort::setViewLabelPosition( ViewLabelPosition thePosition,
526 if( theIsForced && !myViewLabel )
527 myViewLabel = new ViewLabel( viewport() );
532 if( thePosition == VLP_None )
534 myViewLabel->setVisible( false );
538 if( myViewLabelLayout )
539 delete myViewLabelLayout;
541 myViewLabelLayout = new QGridLayout( viewport() );
542 myViewLabelLayout->setMargin( 10 );
543 myViewLabelLayout->setSpacing( 0 );
545 int aRow = 0, aColumn = 0;
546 switch( thePosition )
548 case VLP_TopLeft: aRow = 0; aColumn = 0; break;
549 case VLP_TopRight: aRow = 0; aColumn = 1; break;
550 case VLP_BottomLeft: aRow = 1; aColumn = 0; break;
551 case VLP_BottomRight: aRow = 1; aColumn = 1; break;
555 myViewLabelLayout->addWidget( myViewLabel, aRow, aColumn );
556 myViewLabelLayout->setRowStretch( 1 - aRow, 1 );
557 myViewLabelLayout->setColumnStretch( 1 - aColumn, 1 );
559 myViewLabel->setVisible( true );
562 //================================================================
563 // Function : setViewLabelText
565 //================================================================
566 void GraphicsView_ViewPort::setViewLabelText( const QString& theText )
569 myViewLabel->setText( theText );
572 //================================================================
573 // Function : setMousePositionEnabled
575 //================================================================
576 void GraphicsView_ViewPort::setMousePositionEnabled( bool theState )
578 myIsMousePositionEnabled = theState;
582 setViewLabelPosition( VLP_BottomLeft, true );
584 int aMouseX = 0, aMouseY = 0;
585 setViewLabelText( QString( "(%1, %2)" ).arg( aMouseX ).arg( aMouseY ) );
588 setViewLabelPosition( VLP_None );
591 //================================================================
592 // Function : backgroundColor
594 //================================================================
595 QColor GraphicsView_ViewPort::backgroundColor() const
597 return backgroundBrush().color();
600 //================================================================
601 // Function : setBackgroundColor
603 //================================================================
604 void GraphicsView_ViewPort::setBackgroundColor( const QColor& theColor )
606 setBackgroundBrush( QBrush( theColor ) );
609 //================================================================
610 // Function : setForegroundEnabled
612 //================================================================
613 void GraphicsView_ViewPort::setForegroundEnabled( bool theState )
615 myIsForegroundEnabled = theState;
618 //================================================================
619 // Function : setForegroundSize
621 //================================================================
622 void GraphicsView_ViewPort::setForegroundSize( const QSizeF& theSize )
624 myForegroundSize = theSize;
627 //================================================================
628 // Function : setForegroundMargin
630 //================================================================
631 void GraphicsView_ViewPort::setForegroundMargin( double theMargin )
633 myForegroundMargin = theMargin;
636 //================================================================
637 // Function : setForegroundColor
639 //================================================================
640 void GraphicsView_ViewPort::setForegroundColor( const QColor& theColor )
642 myForegroundColor = theColor;
645 //================================================================
646 // Function : setForegroundFrameColor
648 //================================================================
649 void GraphicsView_ViewPort::setForegroundFrameColor( const QColor& theColor )
651 myForegroundFrameColor = theColor;
654 //================================================================
655 // Function : setForegroundFrameLineWidth
657 //================================================================
658 void GraphicsView_ViewPort::setForegroundFrameLineWidth( double theLineWidth )
660 myForegroundFrameLineWidth = theLineWidth;
663 //================================================================
664 // Function : updateForeground
666 //================================================================
667 void GraphicsView_ViewPort::updateForeground()
669 if( myIsForegroundEnabled )
671 if( !myForegroundItem )
672 myForegroundItem = myScene->addRect( QRectF(), QPen(), QBrush( Qt::white ) );
673 myForegroundItem->setZValue( FOREGROUND_Z_VALUE );
675 QPointF aPoint = QPointF();
676 QRectF aRect( aPoint, myForegroundSize );
677 aRect.adjust( -myForegroundMargin, -myForegroundMargin,
678 myForegroundMargin, myForegroundMargin );
679 myForegroundItem->setRect( aRect );
681 QBrush aBrush = myForegroundItem->brush();
682 aBrush.setColor( myForegroundColor );
683 myForegroundItem->setBrush( aBrush );
685 QPen aPen = myForegroundItem->pen();
686 aPen.setColor( myForegroundFrameColor );
687 aPen.setWidthF( myForegroundFrameLineWidth );
688 myForegroundItem->setPen( aPen );
690 myForegroundItem->setVisible( true );
692 myScene->setSceneRect( aRect.adjusted( -mySceneGap, -mySceneGap, mySceneGap, mySceneGap ) );
696 if( myForegroundItem )
697 myForegroundItem->setVisible( false );
700 updateGrid(); // foreground size could be changed
703 //================================================================
704 // Function : setGridEnabled
706 //================================================================
707 void GraphicsView_ViewPort::setGridEnabled( bool theState )
709 myIsGridEnabled = theState;
712 //================================================================
713 // Function : setGridCellSize
715 //================================================================
716 void GraphicsView_ViewPort::setGridCellSize( int theCellSize )
718 myGridCellSize = theCellSize;
721 //================================================================
722 // Function : setGridLineStyle
724 //================================================================
725 void GraphicsView_ViewPort::setGridLineStyle( int theLineStyle )
727 myGridLineStyle = theLineStyle;
730 //================================================================
731 // Function : setGridLineColor
733 //================================================================
734 void GraphicsView_ViewPort::setGridLineColor( const QColor& theLineColor )
736 myGridLineColor = theLineColor;
739 //================================================================
740 // Function : updateGrid
742 //================================================================
743 void GraphicsView_ViewPort::updateGrid()
745 if( myIsGridEnabled )
748 myGridItem = myScene->addPath( QPainterPath() );
749 myGridItem->setZValue( GRID_Z_VALUE );
751 double aWidth = myForegroundSize.width();
752 double aHeight = myForegroundSize.height();
754 int aGridNbX = int( aWidth / myGridCellSize ) + 1;
755 int aGridNbY = int( aHeight / myGridCellSize ) + 1;
759 for( anIndex = 0; anIndex < aGridNbX; anIndex++ )
761 double x = myGridCellSize * (double)anIndex;
762 aPath.moveTo( x, 0 );
763 aPath.lineTo( x, aHeight );
765 for( anIndex = 0; anIndex < aGridNbY; anIndex++ )
767 double y = myGridCellSize * (double)anIndex;
768 aPath.moveTo( 0, y );
769 aPath.lineTo( aWidth, y );
771 myGridItem->setPath( aPath );
773 QPen aPen = myGridItem->pen();
774 aPen.setStyle( (Qt::PenStyle)myGridLineStyle );
775 aPen.setColor( myGridLineColor );
776 myGridItem->setPen( aPen );
778 myGridItem->setVisible( true );
783 myGridItem->setVisible( false );
787 //================================================================
790 //================================================================
791 void GraphicsView_ViewPort::reset()
796 //================================================================
799 //================================================================
800 void GraphicsView_ViewPort::pan( double theDX, double theDY )
802 myIsTransforming = true;
805 myViewLabel->setAcceptMoveEvents( false );
807 if( QScrollBar* aHBar = horizontalScrollBar() )
808 aHBar->setValue( aHBar->value() - theDX );
809 if( QScrollBar* aVBar = verticalScrollBar() )
810 aVBar->setValue( aVBar->value() + theDY );
813 myViewLabel->setAcceptMoveEvents( true );
815 myIsTransforming = false;
820 //================================================================
821 // Function : setCenter
823 //================================================================
824 void GraphicsView_ViewPort::setCenter( double theX, double theY )
826 myIsTransforming = true;
828 setTransform( myCurrentTransform );
829 centerOn( theX, theY );
831 myIsTransforming = false;
836 //================================================================
839 //================================================================
840 void GraphicsView_ViewPort::zoom( double theX1, double theY1, double theX2, double theY2 )
842 myIsTransforming = true;
844 double aDX = theX2 - theX1;
845 double aDY = theY2 - theY1;
846 double aZoom = sqrt( aDX * aDX + aDY * aDY ) / 100 + 1;
847 aZoom = ( aDX > 0 ) ? aZoom : 1 / aZoom;
849 QTransform aTransform = transform();
850 aTransform.scale( aZoom, aZoom );
851 double aM11 = aTransform.m11();
852 double aM22 = aTransform.m22();
853 // increasing of diagonal coefficients (>300) leads to a crash sometimes
854 // at the values of 100 some primitives are drawn incorrectly
855 if( qMax( aM11, aM22 ) < 100 )
856 setTransform( aTransform );
858 myIsTransforming = false;
863 //================================================================
864 // Function : fitRect
866 //================================================================
867 void GraphicsView_ViewPort::fitRect( const QRectF& theRect )
869 myIsTransforming = true;
871 fitInView( theRect, Qt::KeepAspectRatio );
873 myIsTransforming = false;
878 //================================================================
879 // Function : fitSelect
881 //================================================================
882 void GraphicsView_ViewPort::fitSelect()
884 myIsTransforming = true;
887 for( initSelected(); moreSelected(); nextSelected() )
889 if( GraphicsView_Object* aMovingObject = selectedObject() )
891 QRectF aRect = aMovingObject->getRect();
892 if( aGlobalRect.isNull() )
895 aGlobalRect |= aRect;
899 if( !aGlobalRect.isNull() )
901 double aGap = qMax( aGlobalRect.width(), aGlobalRect.height() ) / 5;
902 aGlobalRect.adjust( -aGap, -aGap, aGap, aGap );
903 fitInView( aGlobalRect, Qt::KeepAspectRatio );
906 myIsTransforming = false;
911 //================================================================
914 //================================================================
915 void GraphicsView_ViewPort::fitAll( bool theKeepScale )
917 myIsTransforming = true;
920 myCurrentTransform = transform();
922 double aGap = myFitAllGap;
923 QRectF aRect = objectsBoundingRect( true );
924 fitInView( aRect.adjusted( -aGap, -aGap, aGap, aGap ), Qt::KeepAspectRatio );
926 myIsTransforming = false;
931 //================================================================
932 // Function : fitWidth
934 //================================================================
935 void GraphicsView_ViewPort::fitWidth()
937 myIsTransforming = true;
939 double aGap = myFitAllGap;
940 QRectF aRect = objectsBoundingRect( true );
942 double aTop = aRect.top();
943 double aLeft = aRect.left();
946 aRect.setY( aRect.center().y() );
947 aRect.setHeight( aMargin );
949 fitInView( aRect.adjusted( -aGap, -aGap, aGap, aGap ), Qt::KeepAspectRatio );
950 ensureVisible( aLeft, aTop, aMargin, aMargin, 0, aGap );
952 myIsTransforming = false;
957 //================================================================
958 // Function : applyTransform
960 //================================================================
961 void GraphicsView_ViewPort::applyTransform()
963 GraphicsView_ObjectListIterator anIter( getObjects() );
964 while( anIter.hasNext() )
965 if( GraphicsView_Object* anObject = anIter.next() )
966 anObject->setViewTransform( transform() );
969 //================================================================
970 // Function : currentBlock
972 //================================================================
973 GraphicsView_ViewPort::BlockStatus GraphicsView_ViewPort::currentBlock()
975 if( isDragging() && !myDragPosition.isNull() )
976 return BlockStatus( BS_Selection );
978 if( myAreSelectionPointsInitialized && ( myFirstSelectionPoint != myLastSelectionPoint ) )
979 return BlockStatus( BS_Selection );
982 return BlockStatus( BS_Selection );
987 //================================================================
988 // Function : highlight
990 //================================================================
991 void GraphicsView_ViewPort::highlight( double theX, double theY )
993 myIsHighlighting = true;
997 bool anIsHighlighted = false;
998 bool anIsOnObject = false;
1000 GraphicsView_Object* aPreviousHighlightedObject = myHighlightedObject;
1001 GraphicsView_Object* aHighlightedObject = 0;
1005 GraphicsView_ObjectList aList = getObjects( SortByZLevel );
1006 GraphicsView_ObjectListIterator anIter( aList );
1007 anIter.toBack(); // objects with higher priority have to be checked earlier
1008 while( anIter.hasPrevious() )
1010 if( GraphicsView_Object* anObject = anIter.previous() )
1012 if( anObject->isVisible() && anObject->isSelectable() )
1014 if( anObject->checkHighlight( theX, theY, aCursor ) )
1016 anIsOnObject = true;
1017 anIsHighlighted = anObject->highlight( theX, theY );
1020 if( anIsHighlighted )
1022 aHighlightedObject = anObject;
1029 setCursor( aCursor );
1034 while( anIter.hasNext() )
1035 if( GraphicsView_Object* anObject = anIter.next() )
1036 anObject->unhighlight();
1038 myHighlightedObject = 0;
1041 else if( !myHighlightedObject && anIsHighlighted )
1043 myHighlightedObject = aHighlightedObject;
1045 else if( myHighlightedObject && !anIsHighlighted )
1047 myHighlightedObject->unhighlight();
1048 myHighlightedObject = 0;
1050 else if( myHighlightedObject && anIsHighlighted )
1052 myHighlightedObject->highlight( theX, theY );
1053 if( myHighlightedObject != aHighlightedObject )
1055 myHighlightedObject->unhighlight();
1056 myHighlightedObject = aHighlightedObject;
1061 //================================================================
1062 // Function : clearHighlighted
1064 //================================================================
1065 void GraphicsView_ViewPort::clearHighlighted()
1067 if( myHighlightedObject )
1069 myHighlightedObject->unhighlight();
1070 myHighlightedObject = 0;
1074 //================================================================
1075 // Function : select
1077 //================================================================
1078 int GraphicsView_ViewPort::select( const QRectF& theRect, bool theIsAppend )
1080 if( !myIsHighlighting )
1081 return GVSS_NoChanged;
1083 GV_SelectionStatus aStatus = GVSS_Invalid;
1084 if( theRect.isNull() ) // point selection
1086 if( myHighlightedObject )
1088 if( mySelectedObjects.count() == 1 &&
1089 mySelectedObjects.first() == myHighlightedObject )
1090 aStatus = GVSS_LocalChanged;
1094 GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1095 while( anIter.hasNext() )
1096 if( GraphicsView_Object* anObject = anIter.next() )
1097 if( myHighlightedObject != anObject )
1098 anObject->unselect();
1100 if( !mySelectedObjects.isEmpty() && aStatus == GVSS_Invalid )
1101 aStatus = GVSS_GlobalChanged;
1102 mySelectedObjects.clear();
1104 else if( myHighlightedObject->isSelected() && aStatus != GVSS_LocalChanged )
1106 mySelectedObjects.removeAll( myHighlightedObject );
1107 myHighlightedObject->unselect();
1109 if( !mySelectedObjects.isEmpty() && aStatus == GVSS_Invalid )
1110 aStatus = GVSS_GlobalChanged;
1115 if( myHighlightedObject->select( myHighlightX, myHighlightY, QRectF() ) &&
1116 mySelectedObjects.indexOf( myHighlightedObject ) == -1 )
1118 mySelectedObjects.append( myHighlightedObject );
1119 if( aStatus == GVSS_Invalid )
1120 aStatus = GVSS_GlobalChanged;
1122 else if( aStatus == GVSS_LocalChanged )
1123 aStatus = GVSS_GlobalChanged;
1128 if( !myHighlightedObject )
1132 GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1133 while( anIter.hasNext() )
1134 if( GraphicsView_Object* anObject = anIter.next() )
1135 if( myHighlightedObject != anObject )
1136 anObject->unselect();
1138 if( !mySelectedObjects.isEmpty() )
1139 aStatus = GVSS_GlobalChanged;
1140 mySelectedObjects.clear();
1145 return GVSS_NoChanged;
1147 else // rectangle selection
1149 aStatus = GVSS_NoChanged;
1151 bool updateAll = false;
1154 if( !mySelectedObjects.isEmpty() )
1155 aStatus = GVSS_GlobalChanged;
1157 GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1158 while( anIter.hasNext() )
1159 if( GraphicsView_Object* anObject = anIter.next() )
1160 if( myHighlightedObject != anObject )
1161 anObject->unselect();
1162 mySelectedObjects.clear();
1165 QListIterator<QGraphicsItem*> anIter( items() );
1166 while( anIter.hasNext() )
1168 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1170 if( anObject->isVisible() && anObject->isSelectable() )
1172 bool anIsSelected = false;
1173 QRectF aRect = anObject->getRect();
1174 if( theRect.contains( aRect ) && myIsHighlighting )
1175 anIsSelected = anObject->select( myHighlightX, myHighlightY, theRect );
1177 if( anIsSelected && mySelectedObjects.indexOf( anObject ) == -1 )
1179 mySelectedObjects.append( anObject );
1180 aStatus = GVSS_GlobalChanged;
1189 //================================================================
1190 // Function : clearSelected
1192 //================================================================
1193 void GraphicsView_ViewPort::clearSelected()
1195 GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1196 while( anIter.hasNext() )
1197 if( GraphicsView_Object* anObject = anIter.next() )
1198 anObject->unselect();
1199 mySelectedObjects.clear();
1202 //================================================================
1203 // Function : setSelected
1205 //================================================================
1206 void GraphicsView_ViewPort::setSelected( GraphicsView_Object* theObject )
1210 theObject->setSelected( true );
1211 mySelectedObjects.append( theObject );
1215 //================================================================
1216 // Function : nbSelected
1218 //================================================================
1219 int GraphicsView_ViewPort::nbSelected() const
1221 return mySelectedObjects.count();
1224 //================================================================
1225 // Function : initSelected
1227 //================================================================
1228 void GraphicsView_ViewPort::initSelected()
1230 mySelectionIterator = 0;
1233 //================================================================
1234 // Function : moreSelected
1236 //================================================================
1237 bool GraphicsView_ViewPort::moreSelected()
1239 return mySelectionIterator < nbSelected();
1242 //================================================================
1243 // Function : nextSelected
1245 //================================================================
1246 bool GraphicsView_ViewPort::nextSelected()
1248 if( mySelectionIterator >= 0 && mySelectionIterator < nbSelected() )
1250 mySelectionIterator++;
1256 //================================================================
1257 // Function : selectedObject
1259 //================================================================
1260 GraphicsView_Object* GraphicsView_ViewPort::selectedObject()
1262 if( mySelectionIterator >= 0 && mySelectionIterator < nbSelected() )
1263 return mySelectedObjects[ mySelectionIterator ];
1267 //================================================================
1268 // Function : startSelectByRect
1270 //================================================================
1271 void GraphicsView_ViewPort::startSelectByRect( int x, int y )
1273 if( !myAreSelectionPointsInitialized )
1275 myFirstSelectionPoint = QPoint( x, y );
1276 myLastSelectionPoint = QPoint( x, y );
1277 myAreSelectionPointsInitialized = true;
1282 myRectBand = new QRubberBand( QRubberBand::Rectangle, this );
1284 palette.setColor( myRectBand->foregroundRole(), Qt::white );
1285 myRectBand->setPalette( palette );
1290 //================================================================
1291 // Function : drawSelectByRect
1293 //================================================================
1294 void GraphicsView_ViewPort::drawSelectByRect( int x, int y )
1296 if( myAreSelectionPointsInitialized )
1300 myLastSelectionPoint.setX( x );
1301 myLastSelectionPoint.setY( y );
1303 QRect aRect = selectionRect();
1304 myRectBand->setGeometry( aRect );
1305 myRectBand->setVisible( aRect.isValid() );
1309 //================================================================
1310 // Function : isSelectByRect
1312 //================================================================
1313 bool GraphicsView_ViewPort::isSelectByRect() const
1315 return myAreSelectionPointsInitialized;
1318 //================================================================
1319 // Function : finishSelectByRect
1321 //================================================================
1322 void GraphicsView_ViewPort::finishSelectByRect()
1324 if( myAreSelectionPointsInitialized )
1333 myAreSelectionPointsInitialized = false;
1337 //================================================================
1338 // Function : selectionRect
1340 //================================================================
1341 QRect GraphicsView_ViewPort::selectionRect()
1344 if( myAreSelectionPointsInitialized )
1346 aRect.setLeft( qMin( myFirstSelectionPoint.x(), myLastSelectionPoint.x() ) );
1347 aRect.setTop( qMin( myFirstSelectionPoint.y(), myLastSelectionPoint.y() ) );
1348 aRect.setRight( qMax( myFirstSelectionPoint.x(), myLastSelectionPoint.x() ) );
1349 aRect.setBottom( qMax( myFirstSelectionPoint.y(), myLastSelectionPoint.y() ) );
1354 //================================================================
1355 // Function : prepareToSketch
1357 //================================================================
1358 void GraphicsView_ViewPort::prepareToSketch( bool theStatus )
1360 myIsPrepareToSketch = theStatus;
1362 setCursor( *getSketchCursor() );
1365 //================================================================
1366 // Function : isPrepareToSketch
1368 //================================================================
1369 bool GraphicsView_ViewPort::isPrepareToSketch()
1371 return myIsPrepareToSketch;
1374 //================================================================
1375 // Function : startSketching
1377 //================================================================
1378 void GraphicsView_ViewPort::startSketching( const QPointF& thePoint,
1381 prepareToSketch( false );
1383 if( !mySketchingItem )
1385 mySketchingItem = new QGraphicsPathItem();
1386 mySketchingItem->setZValue( SKETCH_Z_VALUE );
1388 QPen aPen = mySketchingItem->pen();
1389 aPen.setStyle( Qt::DotLine );
1390 mySketchingItem->setPen( aPen );
1392 addItem( mySketchingItem );
1395 mySketchingPoint = thePoint;
1398 aPath.moveTo( mySketchingPoint );
1399 mySketchingItem->setPath( aPath );
1400 mySketchingItem->setVisible( true );
1402 myIsSketching = true;
1403 myIsSketchingByPath = theIsPath;
1406 //================================================================
1407 // Function : drawSketching
1409 //================================================================
1410 void GraphicsView_ViewPort::drawSketching( const QPointF& thePoint )
1412 bool anIsPath = false;
1413 if( mySketchingItem && isSketching( &anIsPath ) )
1415 QPainterPath aPath = mySketchingItem->path();
1416 if( anIsPath ) // arbitrary path
1417 aPath.lineTo( thePoint );
1420 // make a valid rectangle
1421 double x1 = mySketchingPoint.x(), y1 = mySketchingPoint.y();
1422 double x2 = thePoint.x(), y2 = thePoint.y();
1423 QPointF aPoint1( qMin( x1, x2 ), qMin( y1, y2 ) );
1424 QPointF aPoint2( qMax( x1, x2 ), qMax( y1, y2 ) );
1425 QRectF aRect( aPoint1, aPoint2 );
1427 aPath = QPainterPath();
1428 aPath.addRect( aRect );
1430 mySketchingItem->setPath( aPath );
1434 //================================================================
1435 // Function : finishSketching
1437 //================================================================
1438 void GraphicsView_ViewPort::finishSketching( bool theStatus )
1440 prepareToSketch( false );
1442 mySketchingItem->setVisible( false );
1443 myIsSketching = false;
1445 setCursor( *getDefaultCursor() );
1449 QPainterPath aPath = mySketchingItem->path();
1450 emit vpSketchingFinished( aPath );
1454 //================================================================
1455 // Function : isSketching
1457 //================================================================
1458 bool GraphicsView_ViewPort::isSketching( bool* theIsPath ) const
1461 *theIsPath = myIsSketchingByPath;
1462 return myIsSketching;
1465 //================================================================
1466 // Function : dragObjects
1468 //================================================================
1469 void GraphicsView_ViewPort::dragObjects( QGraphicsSceneMouseEvent* e )
1471 GraphicsView_Object* anObject = getHighlightedObject();
1473 if( myDragPosition.isNull() )
1475 myDragPosition = e->scenePos();
1479 GraphicsView_ObjectList anObjectsToMove;
1480 if( anObject && anObject->isMovable() && ( e->buttons() & Qt::LeftButton ) )
1482 if( anObject->isSelected() )
1484 for( initSelected(); moreSelected(); nextSelected() )
1485 if( GraphicsView_Object* aMovingObject = selectedObject() )
1486 if( aMovingObject->isMovable() )
1487 anObjectsToMove.append( aMovingObject );
1490 anObjectsToMove.append( anObject );
1492 else if( hasInteractionFlag( DraggingByMiddleButton ) &&
1493 nbSelected() && ( e->buttons() & Qt::MidButton ) )
1495 for( initSelected(); moreSelected(); nextSelected() )
1496 if( GraphicsView_Object* aMovingObject = selectedObject() )
1497 if( aMovingObject->isMovable() )
1498 anObjectsToMove.append( aMovingObject );
1501 if( anObjectsToMove.isEmpty() )
1504 double aDX = e->scenePos().x() - myDragPosition.x();
1505 double aDY = e->scenePos().y() - myDragPosition.y();
1507 bool anIsMovingByXAllowed = true, anIsMovingByYAllowed = true;
1508 GraphicsView_ObjectListIterator anIter( anObjectsToMove );
1509 while( anIter.hasNext() )
1510 if( GraphicsView_Object* aMovingObject = anIter.next() )
1512 if( !aMovingObject->isMovingByXAllowed( aDX ) )
1513 anIsMovingByXAllowed = false;
1514 if( !aMovingObject->isMovingByYAllowed( aDY ) )
1515 anIsMovingByYAllowed = false;
1518 if( !anIsMovingByXAllowed && !anIsMovingByYAllowed )
1519 return; // myDragPosition shouldn't be changed
1521 if( !anIsMovingByXAllowed )
1524 if( !anIsMovingByYAllowed )
1527 anIter = anObjectsToMove;
1528 while( anIter.hasNext() )
1529 if( GraphicsView_Object* aMovingObject = anIter.next() )
1530 aMovingObject->move( aDX, aDY );
1532 if( anIsMovingByXAllowed )
1533 myDragPosition.setX( e->scenePos().x() );
1535 if( anIsMovingByYAllowed )
1536 myDragPosition.setY( e->scenePos().y() );
1539 //================================================================
1540 // Function : startPulling
1542 //================================================================
1543 bool GraphicsView_ViewPort::startPulling( const QPointF& thePoint )
1545 QListIterator<QGraphicsItem*> anIter( items() );
1546 while( anIter.hasNext() )
1548 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1550 QRectF aRect = anObject->getPullingRect();
1551 if( aRect.contains( thePoint ) && anObject->startPulling( thePoint ) )
1554 myPullingObject = anObject;
1555 //setCursor( *getHandCursor() ); // testing ImageViewer
1563 //================================================================
1564 // Function : drawPulling
1566 //================================================================
1567 void GraphicsView_ViewPort::drawPulling( const QPointF& thePoint )
1569 GraphicsView_Object* aLockedObject = 0;
1571 QListIterator<QGraphicsItem*> anIter( items() );
1572 while( anIter.hasNext() )
1574 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1576 if( !anObject->isVisible() )
1579 QRectF aRect = anObject->getPullingRect();
1580 if( aRect.contains( thePoint ) && anObject->portContains( thePoint ) )
1582 aLockedObject = anObject;
1588 myPullingObject->pull( thePoint, aLockedObject, getSelectedObjects() );
1591 //================================================================
1592 // Function : finishPulling
1594 //================================================================
1595 void GraphicsView_ViewPort::finishPulling( bool theStatus )
1597 myIsPulling = false;
1598 myPullingObject->finishPulling( theStatus, getSelectedObjects() );
1599 setCursor( *getDefaultCursor() );
1602 //================================================================
1603 // Function : cancelCurrentOperation
1605 //================================================================
1606 bool GraphicsView_ViewPort::cancelCurrentOperation()
1608 myIsHighlighting = false;
1612 for( initSelected(); moreSelected(); nextSelected() )
1613 if( GraphicsView_Object* aMovingObject = selectedObject() )
1614 aMovingObject->finishMove( false );
1616 if( GraphicsView_Object* aMovingObject = getHighlightedObject() )
1617 aMovingObject->finishMove( false );
1619 myIsDragging = false;
1620 myDragPosition = QPointF();
1621 //setCursor( myStoredCursor );
1622 setCursor( *getDefaultCursor() );
1629 finishPulling( false );
1633 if( isSketching() || isPrepareToSketch() )
1635 finishSketching( false );
1642 //================================================================
1643 // Function : onBoundingRectChanged
1645 //================================================================
1646 void GraphicsView_ViewPort::onBoundingRectChanged()
1648 if( hasInteractionFlag( TraceBoundingRect ) )
1650 QRectF aRect = objectsBoundingRect( true );
1651 myScene->setSceneRect( aRect.adjusted( -mySceneGap, -mySceneGap, mySceneGap, mySceneGap ) );
1655 //================================================================
1656 // Function : onKeyEvent
1658 //================================================================
1659 void GraphicsView_ViewPort::onKeyEvent( QKeyEvent* e )
1661 emit vpKeyEvent( e );
1664 //================================================================
1665 // Function : onMouseEvent
1667 //================================================================
1668 void GraphicsView_ViewPort::onMouseEvent( QGraphicsSceneMouseEvent* e )
1670 emit vpMouseEvent( e );
1672 bool anIsHandled = false;
1675 case QEvent::GraphicsSceneMousePress:
1677 if( hasInteractionFlag( EditFlags ) && nbSelected() )
1678 for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1679 if( GraphicsView_Object* anObject = selectedObject() )
1680 anIsHandled = anObject->handleMousePress( e );
1682 if( !anIsHandled && hasInteractionFlag( Dragging ) )
1684 bool anAccel = e->modifiers() & GraphicsView_ViewTransformer::accelKey();
1685 if( ( getHighlightedObject() &&
1686 getHighlightedObject()->isMovable() &&
1687 !( anAccel || e->button() != Qt::LeftButton ) ) ||
1688 ( hasInteractionFlag( DraggingByMiddleButton ) &&
1689 nbSelected() && !anAccel && e->button() == Qt::MidButton ) )
1691 myIsDragging = true;
1692 myStoredCursor = cursor();
1693 setCursor( Qt::ClosedHandCursor );
1698 case QEvent::GraphicsSceneMouseMove:
1700 if( hasInteractionFlag( EditFlags ) && nbSelected() )
1701 for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1702 if( GraphicsView_Object* anObject = selectedObject() )
1703 anIsHandled = anObject->handleMouseMove( e );
1705 if( !anIsHandled && !isPulling() && myIsDragging )
1709 case QEvent::GraphicsSceneMouseRelease:
1711 if( hasInteractionFlag( EditFlags ) && nbSelected() )
1712 for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1713 if( GraphicsView_Object* anObject = selectedObject() )
1714 anIsHandled = anObject->handleMouseRelease( e );
1716 if( !anIsHandled && !isPulling() && myIsDragging )
1718 emit vpObjectBeforeMoving();
1720 bool anIsMoved = false;
1721 for( initSelected(); moreSelected(); nextSelected() )
1722 if( GraphicsView_Object* aMovingObject = selectedObject() )
1723 anIsMoved = aMovingObject->finishMove( true ) || anIsMoved;
1725 if( GraphicsView_Object* aMovingObject = getHighlightedObject() )
1726 anIsMoved = aMovingObject->finishMove( true ) || anIsMoved;
1728 myIsDragging = false;
1729 myDragPosition = QPointF();
1730 setCursor( myStoredCursor );
1732 emit vpObjectAfterMoving( anIsMoved );
1736 case QEvent::GraphicsSceneMouseDoubleClick:
1737 break; // do nothing, just emit the signal
1742 if( myIsMousePositionEnabled )
1744 int aMouseX = (int)e->scenePos().x();
1745 int aMouseY = (int)e->scenePos().y();
1746 setViewLabelText( QString( "(%1, %2)" ).arg( aMouseX ).arg( aMouseY ) );
1750 //================================================================
1751 // Function : onWheelEvent
1753 //================================================================
1754 void GraphicsView_ViewPort::onWheelEvent( QGraphicsSceneWheelEvent* e )
1756 emit vpWheelEvent( e );
1759 //================================================================
1760 // Function : onContextMenuEvent
1762 //================================================================
1763 void GraphicsView_ViewPort::onContextMenuEvent( QGraphicsSceneContextMenuEvent* e )
1765 emit vpContextMenuEvent( e );
1768 //================================================================
1769 // Function : scrollContentsBy
1771 //================================================================
1772 void GraphicsView_ViewPort::scrollContentsBy( int theDX, int theDY )
1775 myViewLabel->setAcceptMoveEvents( false );
1777 QGraphicsView::scrollContentsBy( theDX, theDY );
1780 myViewLabel->setAcceptMoveEvents( true );