1 // Copyright (C) 2013-2014 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 : removeItem
277 //================================================================
278 void GraphicsView_ViewPort::removeItem( QGraphicsItem* theItem )
280 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( theItem ) )
282 if( myHighlightedObject == anObject )
283 myHighlightedObject = 0;
284 mySelectedObjects.removeAll( anObject );
285 myObjects.removeAll( anObject );
286 anObject->removeFrom( this );
289 myScene->removeItem( theItem );
290 onBoundingRectChanged();
293 //================================================================
294 // Function : getObjects
296 //================================================================
297 GraphicsView_ObjectList GraphicsView_ViewPort::getObjects( SortType theSortType ) const
299 if( theSortType == SelectedFirst )
301 // to append selected objects after their non-selected siblings with similar priority
302 int aCurrentPriority = -1;
303 GraphicsView_ObjectList aSelectedObjects;
304 GraphicsView_ObjectList aTopmostObjects;
306 GraphicsView_ObjectList aList;
307 GraphicsView_ObjectListIterator anIter( myObjects );
308 while( anIter.hasNext() )
310 if( GraphicsView_Object* anObject = anIter.next() )
312 if( anObject->isOnTop() )
314 aTopmostObjects.append( anObject );
318 int aPriority = anObject->getPriority();
319 if( aPriority > aCurrentPriority )
321 if( !aSelectedObjects.isEmpty() )
323 aList.append( aSelectedObjects );
324 aSelectedObjects.clear();
326 aCurrentPriority = aPriority;
329 if( anObject->isSelected() )
330 aSelectedObjects.append( anObject );
332 aList.append( anObject );
336 // for selected objects with highest priority,
337 // which were not pushed to the result list yet
338 if( !aSelectedObjects.isEmpty() )
340 aList.append( aSelectedObjects );
341 aSelectedObjects.clear();
344 aList.append( aTopmostObjects );
349 if( theSortType == SortByZLevel ) // double loop, needs to be optimized
351 GraphicsView_ObjectList aList;
353 GraphicsView_ObjectListIterator anIter( myObjects );
354 while( anIter.hasNext() )
356 if( GraphicsView_Object* anObject = anIter.next() )
358 double aZValue = anObject->zValue();
359 GraphicsView_ObjectList::iterator anIter1, anIter1End = aList.end();
360 for( anIter1 = aList.begin(); anIter1 != anIter1End; anIter1++ )
361 if( GraphicsView_Object* anObjectRef = *anIter1 )
362 if( anObjectRef->zValue() > aZValue )
364 aList.insert( anIter1, anObject );
370 return myObjects; // theSortType == NoSorting
373 //================================================================
374 // Function : objectsBoundingRect
376 //================================================================
377 QRectF GraphicsView_ViewPort::objectsBoundingRect( bool theOnlyVisible ) const
380 QListIterator<QGraphicsItem*> anIter( items() );
381 while( anIter.hasNext() )
383 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
385 if( theOnlyVisible && !anObject->isVisible() )
388 QRectF anObjectRect = anObject->getRect();
389 if( !anObjectRect.isNull() )
392 aRect = anObject->getRect();
394 aRect |= anObject->getRect();
401 //================================================================
402 // Function : dumpView
404 //================================================================
405 QImage GraphicsView_ViewPort::dumpView( bool theWholeScene,
408 if( !theWholeScene ) // just grab the view contents
410 QPixmap aPixmap = QPixmap::grabWindow( viewport()->winId() );
411 return aPixmap.toImage();
414 // get a bounding rect of all presented objects
415 // (itemsBoundingRect() method is unsuitable)
416 QRectF aRect = objectsBoundingRect();
420 QRectF aTargetRect( 0, 0, aRect.width(), aRect.height() );
421 if( theSize.isValid() )
423 double aRatioX = theSize.width() / aTargetRect.width();
424 double aRatioY = theSize.height() / aTargetRect.height();
425 double aRatio = qMin( aRatioX, aRatioY );
426 aTargetRect.setWidth( aTargetRect.width() * aRatio );
427 aTargetRect.setHeight( aTargetRect.height() * aRatio );
430 // render the scene to an image
431 QImage anImage( aTargetRect.toRect().size(), QImage::Format_RGB32 );
432 QPainter aPainter( &anImage );
433 aPainter.setRenderHints( renderHints() );
435 myScene->render( &aPainter, aTargetRect, aRect );
440 //================================================================
441 // Function : setSceneGap
443 //================================================================
444 void GraphicsView_ViewPort::setSceneGap( double theSceneGap )
446 mySceneGap = theSceneGap;
447 onBoundingRectChanged();
450 //================================================================
451 // Function : setFitAllGap
453 //================================================================
454 void GraphicsView_ViewPort::setFitAllGap( double theFitAllGap )
456 myFitAllGap = theFitAllGap;
459 //================================================================
460 // Function : interactionFlags
462 //================================================================
463 int GraphicsView_ViewPort::interactionFlags() const
465 return myInteractionFlags;
468 //================================================================
469 // Function : hasInteractionFlag
471 //================================================================
472 bool GraphicsView_ViewPort::hasInteractionFlag( InteractionFlag theFlag )
474 return ( interactionFlags() & theFlag ) == theFlag;
477 //================================================================
478 // Function : setInteractionFlag
480 //================================================================
481 void GraphicsView_ViewPort::setInteractionFlag( InteractionFlag theFlag,
485 setInteractionFlags( myInteractionFlags | theFlag );
487 setInteractionFlags( myInteractionFlags & ~theFlag );
490 //================================================================
491 // Function : setInteractionFlags
493 //================================================================
494 void GraphicsView_ViewPort::setInteractionFlags( InteractionFlags theFlags )
496 myInteractionFlags = theFlags;
499 //================================================================
500 // Function : setViewLabelPosition
502 //================================================================
503 void GraphicsView_ViewPort::setViewLabelPosition( ViewLabelPosition thePosition,
506 if( theIsForced && !myViewLabel )
507 myViewLabel = new ViewLabel( viewport() );
512 if( thePosition == VLP_None )
514 myViewLabel->setVisible( false );
518 if( myViewLabelLayout )
519 delete myViewLabelLayout;
521 myViewLabelLayout = new QGridLayout( viewport() );
522 myViewLabelLayout->setMargin( 10 );
523 myViewLabelLayout->setSpacing( 0 );
525 int aRow = 0, aColumn = 0;
526 switch( thePosition )
528 case VLP_TopLeft: aRow = 0; aColumn = 0; break;
529 case VLP_TopRight: aRow = 0; aColumn = 1; break;
530 case VLP_BottomLeft: aRow = 1; aColumn = 0; break;
531 case VLP_BottomRight: aRow = 1; aColumn = 1; break;
535 myViewLabelLayout->addWidget( myViewLabel, aRow, aColumn );
536 myViewLabelLayout->setRowStretch( 1 - aRow, 1 );
537 myViewLabelLayout->setColumnStretch( 1 - aColumn, 1 );
539 myViewLabel->setVisible( true );
542 //================================================================
543 // Function : setViewLabelText
545 //================================================================
546 void GraphicsView_ViewPort::setViewLabelText( const QString& theText )
549 myViewLabel->setText( theText );
552 //================================================================
553 // Function : setMousePositionEnabled
555 //================================================================
556 void GraphicsView_ViewPort::setMousePositionEnabled( bool theState )
558 myIsMousePositionEnabled = theState;
562 setViewLabelPosition( VLP_BottomLeft, true );
564 int aMouseX = 0, aMouseY = 0;
565 setViewLabelText( QString( "(%1, %2)" ).arg( aMouseX ).arg( aMouseY ) );
568 setViewLabelPosition( VLP_None );
571 //================================================================
572 // Function : backgroundColor
574 //================================================================
575 QColor GraphicsView_ViewPort::backgroundColor() const
577 return backgroundBrush().color();
580 //================================================================
581 // Function : setBackgroundColor
583 //================================================================
584 void GraphicsView_ViewPort::setBackgroundColor( const QColor& theColor )
586 setBackgroundBrush( QBrush( theColor ) );
589 //================================================================
590 // Function : setForegroundEnabled
592 //================================================================
593 void GraphicsView_ViewPort::setForegroundEnabled( bool theState )
595 myIsForegroundEnabled = theState;
598 //================================================================
599 // Function : setForegroundSize
601 //================================================================
602 void GraphicsView_ViewPort::setForegroundSize( const QSizeF& theSize )
604 myForegroundSize = theSize;
607 //================================================================
608 // Function : setForegroundMargin
610 //================================================================
611 void GraphicsView_ViewPort::setForegroundMargin( double theMargin )
613 myForegroundMargin = theMargin;
616 //================================================================
617 // Function : setForegroundColor
619 //================================================================
620 void GraphicsView_ViewPort::setForegroundColor( const QColor& theColor )
622 myForegroundColor = theColor;
625 //================================================================
626 // Function : setForegroundFrameColor
628 //================================================================
629 void GraphicsView_ViewPort::setForegroundFrameColor( const QColor& theColor )
631 myForegroundFrameColor = theColor;
634 //================================================================
635 // Function : setForegroundFrameLineWidth
637 //================================================================
638 void GraphicsView_ViewPort::setForegroundFrameLineWidth( double theLineWidth )
640 myForegroundFrameLineWidth = theLineWidth;
643 //================================================================
644 // Function : updateForeground
646 //================================================================
647 void GraphicsView_ViewPort::updateForeground()
649 if( myIsForegroundEnabled )
651 if( !myForegroundItem )
652 myForegroundItem = myScene->addRect( QRectF(), QPen(), QBrush( Qt::white ) );
653 myForegroundItem->setZValue( FOREGROUND_Z_VALUE );
655 QPointF aPoint = QPointF();
656 QRectF aRect( aPoint, myForegroundSize );
657 aRect.adjust( -myForegroundMargin, -myForegroundMargin,
658 myForegroundMargin, myForegroundMargin );
659 myForegroundItem->setRect( aRect );
661 QBrush aBrush = myForegroundItem->brush();
662 aBrush.setColor( myForegroundColor );
663 myForegroundItem->setBrush( aBrush );
665 QPen aPen = myForegroundItem->pen();
666 aPen.setColor( myForegroundFrameColor );
667 aPen.setWidthF( myForegroundFrameLineWidth );
668 myForegroundItem->setPen( aPen );
670 myForegroundItem->setVisible( true );
672 myScene->setSceneRect( aRect.adjusted( -mySceneGap, -mySceneGap, mySceneGap, mySceneGap ) );
676 if( myForegroundItem )
677 myForegroundItem->setVisible( false );
680 updateGrid(); // foreground size could be changed
683 //================================================================
684 // Function : setGridEnabled
686 //================================================================
687 void GraphicsView_ViewPort::setGridEnabled( bool theState )
689 myIsGridEnabled = theState;
692 //================================================================
693 // Function : setGridCellSize
695 //================================================================
696 void GraphicsView_ViewPort::setGridCellSize( int theCellSize )
698 myGridCellSize = theCellSize;
701 //================================================================
702 // Function : setGridLineStyle
704 //================================================================
705 void GraphicsView_ViewPort::setGridLineStyle( int theLineStyle )
707 myGridLineStyle = theLineStyle;
710 //================================================================
711 // Function : setGridLineColor
713 //================================================================
714 void GraphicsView_ViewPort::setGridLineColor( const QColor& theLineColor )
716 myGridLineColor = theLineColor;
719 //================================================================
720 // Function : updateGrid
722 //================================================================
723 void GraphicsView_ViewPort::updateGrid()
725 if( myIsGridEnabled )
728 myGridItem = myScene->addPath( QPainterPath() );
729 myGridItem->setZValue( GRID_Z_VALUE );
731 double aWidth = myForegroundSize.width();
732 double aHeight = myForegroundSize.height();
734 int aGridNbX = int( aWidth / myGridCellSize ) + 1;
735 int aGridNbY = int( aHeight / myGridCellSize ) + 1;
739 for( anIndex = 0; anIndex < aGridNbX; anIndex++ )
741 double x = myGridCellSize * (double)anIndex;
742 aPath.moveTo( x, 0 );
743 aPath.lineTo( x, aHeight );
745 for( anIndex = 0; anIndex < aGridNbY; anIndex++ )
747 double y = myGridCellSize * (double)anIndex;
748 aPath.moveTo( 0, y );
749 aPath.lineTo( aWidth, y );
751 myGridItem->setPath( aPath );
753 QPen aPen = myGridItem->pen();
754 aPen.setStyle( (Qt::PenStyle)myGridLineStyle );
755 aPen.setColor( myGridLineColor );
756 myGridItem->setPen( aPen );
758 myGridItem->setVisible( true );
763 myGridItem->setVisible( false );
767 //================================================================
770 //================================================================
771 void GraphicsView_ViewPort::reset()
776 //================================================================
779 //================================================================
780 void GraphicsView_ViewPort::pan( double theDX, double theDY )
782 myIsTransforming = true;
785 myViewLabel->setAcceptMoveEvents( false );
787 if( QScrollBar* aHBar = horizontalScrollBar() )
788 aHBar->setValue( aHBar->value() - theDX );
789 if( QScrollBar* aVBar = verticalScrollBar() )
790 aVBar->setValue( aVBar->value() + theDY );
793 myViewLabel->setAcceptMoveEvents( true );
795 myIsTransforming = false;
800 //================================================================
801 // Function : setCenter
803 //================================================================
804 void GraphicsView_ViewPort::setCenter( double theX, double theY )
806 myIsTransforming = true;
808 setTransform( myCurrentTransform );
809 centerOn( theX, theY );
811 myIsTransforming = false;
816 //================================================================
819 //================================================================
820 void GraphicsView_ViewPort::zoom( double theX1, double theY1, double theX2, double theY2 )
822 myIsTransforming = true;
824 double aDX = theX2 - theX1;
825 double aDY = theY2 - theY1;
826 double aZoom = sqrt( aDX * aDX + aDY * aDY ) / 100 + 1;
827 aZoom = ( aDX > 0 ) ? aZoom : 1 / aZoom;
829 QTransform aTransform = transform();
830 aTransform.scale( aZoom, aZoom );
831 double aM11 = aTransform.m11();
832 double aM22 = aTransform.m22();
833 // increasing of diagonal coefficients (>300) leads to a crash sometimes
834 // at the values of 100 some primitives are drawn incorrectly
835 if( qMax( aM11, aM22 ) < 100 )
836 setTransform( aTransform );
838 myIsTransforming = false;
843 //================================================================
844 // Function : fitRect
846 //================================================================
847 void GraphicsView_ViewPort::fitRect( const QRectF& theRect )
849 myIsTransforming = true;
851 fitInView( theRect, Qt::KeepAspectRatio );
853 myIsTransforming = false;
858 //================================================================
859 // Function : fitSelect
861 //================================================================
862 void GraphicsView_ViewPort::fitSelect()
864 myIsTransforming = true;
867 for( initSelected(); moreSelected(); nextSelected() )
869 if( GraphicsView_Object* aMovingObject = selectedObject() )
871 QRectF aRect = aMovingObject->getRect();
872 if( aGlobalRect.isNull() )
875 aGlobalRect |= aRect;
879 if( !aGlobalRect.isNull() )
881 double aGap = qMax( aGlobalRect.width(), aGlobalRect.height() ) / 5;
882 aGlobalRect.adjust( -aGap, -aGap, aGap, aGap );
883 fitInView( aGlobalRect, Qt::KeepAspectRatio );
886 myIsTransforming = false;
891 //================================================================
894 //================================================================
895 void GraphicsView_ViewPort::fitAll( bool theKeepScale )
897 myIsTransforming = true;
900 myCurrentTransform = transform();
902 double aGap = myFitAllGap;
903 QRectF aRect = objectsBoundingRect( true );
904 fitInView( aRect.adjusted( -aGap, -aGap, aGap, aGap ), Qt::KeepAspectRatio );
906 myIsTransforming = false;
911 //================================================================
912 // Function : fitWidth
914 //================================================================
915 void GraphicsView_ViewPort::fitWidth()
917 myIsTransforming = true;
919 double aGap = myFitAllGap;
920 QRectF aRect = objectsBoundingRect( true );
922 double aTop = aRect.top();
923 double aLeft = aRect.left();
926 aRect.setY( aRect.center().y() );
927 aRect.setHeight( aMargin );
929 fitInView( aRect.adjusted( -aGap, -aGap, aGap, aGap ), Qt::KeepAspectRatio );
930 ensureVisible( aLeft, aTop, aMargin, aMargin, 0, aGap );
932 myIsTransforming = false;
937 //================================================================
938 // Function : applyTransform
940 //================================================================
941 void GraphicsView_ViewPort::applyTransform()
943 GraphicsView_ObjectListIterator anIter( getObjects() );
944 while( anIter.hasNext() )
945 if( GraphicsView_Object* anObject = anIter.next() )
946 anObject->setViewTransform( transform() );
949 //================================================================
950 // Function : currentBlock
952 //================================================================
953 GraphicsView_ViewPort::BlockStatus GraphicsView_ViewPort::currentBlock()
955 if( isDragging() && !myDragPosition.isNull() )
956 return BlockStatus( BS_Selection );
958 if( myAreSelectionPointsInitialized && ( myFirstSelectionPoint != myLastSelectionPoint ) )
959 return BlockStatus( BS_Selection );
962 return BlockStatus( BS_Selection );
967 //================================================================
968 // Function : highlight
970 //================================================================
971 void GraphicsView_ViewPort::highlight( double theX, double theY )
973 myIsHighlighting = true;
977 bool anIsHighlighted = false;
978 bool anIsOnObject = false;
980 GraphicsView_Object* aPreviousHighlightedObject = myHighlightedObject;
981 GraphicsView_Object* aHighlightedObject = 0;
985 GraphicsView_ObjectList aList = getObjects( SortByZLevel );
986 GraphicsView_ObjectListIterator anIter( aList );
987 anIter.toBack(); // objects with higher priority have to be checked earlier
988 while( anIter.hasPrevious() )
990 if( GraphicsView_Object* anObject = anIter.previous() )
992 if( anObject->isVisible() && anObject->isSelectable() )
994 if( anObject->checkHighlight( theX, theY, aCursor ) )
997 anIsHighlighted = anObject->highlight( theX, theY );
1000 if( anIsHighlighted )
1002 aHighlightedObject = anObject;
1009 setCursor( aCursor );
1014 while( anIter.hasNext() )
1015 if( GraphicsView_Object* anObject = anIter.next() )
1016 anObject->unhighlight();
1018 myHighlightedObject = 0;
1021 else if( !myHighlightedObject && anIsHighlighted )
1023 myHighlightedObject = aHighlightedObject;
1025 else if( myHighlightedObject && !anIsHighlighted )
1027 myHighlightedObject->unhighlight();
1028 myHighlightedObject = 0;
1030 else if( myHighlightedObject && anIsHighlighted )
1032 myHighlightedObject->highlight( theX, theY );
1033 if( myHighlightedObject != aHighlightedObject )
1035 myHighlightedObject->unhighlight();
1036 myHighlightedObject = aHighlightedObject;
1041 //================================================================
1042 // Function : clearHighlighted
1044 //================================================================
1045 void GraphicsView_ViewPort::clearHighlighted()
1047 if( myHighlightedObject )
1049 myHighlightedObject->unhighlight();
1050 myHighlightedObject = 0;
1054 //================================================================
1055 // Function : select
1057 //================================================================
1058 int GraphicsView_ViewPort::select( const QRectF& theRect, bool theIsAppend )
1060 if( !myIsHighlighting )
1061 return GVSS_NoChanged;
1063 GV_SelectionStatus aStatus = GVSS_Invalid;
1064 if( theRect.isNull() ) // point selection
1066 if( myHighlightedObject )
1068 if( mySelectedObjects.count() == 1 &&
1069 mySelectedObjects.first() == myHighlightedObject )
1070 aStatus = GVSS_LocalChanged;
1074 GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1075 while( anIter.hasNext() )
1076 if( GraphicsView_Object* anObject = anIter.next() )
1077 if( myHighlightedObject != anObject )
1078 anObject->unselect();
1080 if( !mySelectedObjects.isEmpty() && aStatus == GVSS_Invalid )
1081 aStatus = GVSS_GlobalChanged;
1082 mySelectedObjects.clear();
1084 else if( myHighlightedObject->isSelected() && aStatus != GVSS_LocalChanged )
1086 mySelectedObjects.removeAll( myHighlightedObject );
1087 myHighlightedObject->unselect();
1089 if( !mySelectedObjects.isEmpty() && aStatus == GVSS_Invalid )
1090 aStatus = GVSS_GlobalChanged;
1095 if( myHighlightedObject->select( myHighlightX, myHighlightY, QRectF() ) &&
1096 mySelectedObjects.indexOf( myHighlightedObject ) == -1 )
1098 mySelectedObjects.append( myHighlightedObject );
1099 if( aStatus == GVSS_Invalid )
1100 aStatus = GVSS_GlobalChanged;
1102 else if( aStatus == GVSS_LocalChanged )
1103 aStatus = GVSS_GlobalChanged;
1108 if( !myHighlightedObject )
1112 GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1113 while( anIter.hasNext() )
1114 if( GraphicsView_Object* anObject = anIter.next() )
1115 if( myHighlightedObject != anObject )
1116 anObject->unselect();
1118 if( !mySelectedObjects.isEmpty() )
1119 aStatus = GVSS_GlobalChanged;
1120 mySelectedObjects.clear();
1125 return GVSS_NoChanged;
1127 else // rectangle selection
1129 aStatus = GVSS_NoChanged;
1131 bool updateAll = false;
1134 if( !mySelectedObjects.isEmpty() )
1135 aStatus = GVSS_GlobalChanged;
1137 GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1138 while( anIter.hasNext() )
1139 if( GraphicsView_Object* anObject = anIter.next() )
1140 if( myHighlightedObject != anObject )
1141 anObject->unselect();
1142 mySelectedObjects.clear();
1145 QListIterator<QGraphicsItem*> anIter( items() );
1146 while( anIter.hasNext() )
1148 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1150 if( anObject->isVisible() && anObject->isSelectable() )
1152 bool anIsSelected = false;
1153 QRectF aRect = anObject->getRect();
1154 if( theRect.contains( aRect ) && myIsHighlighting )
1155 anIsSelected = anObject->select( myHighlightX, myHighlightY, theRect );
1157 if( anIsSelected && mySelectedObjects.indexOf( anObject ) == -1 )
1159 mySelectedObjects.append( anObject );
1160 aStatus = GVSS_GlobalChanged;
1169 //================================================================
1170 // Function : clearSelected
1172 //================================================================
1173 void GraphicsView_ViewPort::clearSelected()
1175 GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1176 while( anIter.hasNext() )
1177 if( GraphicsView_Object* anObject = anIter.next() )
1178 anObject->unselect();
1179 mySelectedObjects.clear();
1182 //================================================================
1183 // Function : setSelected
1185 //================================================================
1186 void GraphicsView_ViewPort::setSelected( GraphicsView_Object* theObject )
1190 theObject->setSelected( true );
1191 mySelectedObjects.append( theObject );
1195 //================================================================
1196 // Function : nbSelected
1198 //================================================================
1199 int GraphicsView_ViewPort::nbSelected() const
1201 return mySelectedObjects.count();
1204 //================================================================
1205 // Function : initSelected
1207 //================================================================
1208 void GraphicsView_ViewPort::initSelected()
1210 mySelectionIterator = 0;
1213 //================================================================
1214 // Function : moreSelected
1216 //================================================================
1217 bool GraphicsView_ViewPort::moreSelected()
1219 return mySelectionIterator < nbSelected();
1222 //================================================================
1223 // Function : nextSelected
1225 //================================================================
1226 bool GraphicsView_ViewPort::nextSelected()
1228 if( mySelectionIterator >= 0 && mySelectionIterator < nbSelected() )
1230 mySelectionIterator++;
1236 //================================================================
1237 // Function : selectedObject
1239 //================================================================
1240 GraphicsView_Object* GraphicsView_ViewPort::selectedObject()
1242 if( mySelectionIterator >= 0 && mySelectionIterator < nbSelected() )
1243 return mySelectedObjects[ mySelectionIterator ];
1247 //================================================================
1248 // Function : startSelectByRect
1250 //================================================================
1251 void GraphicsView_ViewPort::startSelectByRect( int x, int y )
1253 if( !myAreSelectionPointsInitialized )
1255 myFirstSelectionPoint = QPoint( x, y );
1256 myLastSelectionPoint = QPoint( x, y );
1257 myAreSelectionPointsInitialized = true;
1262 myRectBand = new QRubberBand( QRubberBand::Rectangle, this );
1264 palette.setColor( myRectBand->foregroundRole(), Qt::white );
1265 myRectBand->setPalette( palette );
1270 //================================================================
1271 // Function : drawSelectByRect
1273 //================================================================
1274 void GraphicsView_ViewPort::drawSelectByRect( int x, int y )
1276 if( myAreSelectionPointsInitialized )
1280 myLastSelectionPoint.setX( x );
1281 myLastSelectionPoint.setY( y );
1283 QRect aRect = selectionRect();
1284 myRectBand->setGeometry( aRect );
1285 myRectBand->setVisible( aRect.isValid() );
1289 //================================================================
1290 // Function : isSelectByRect
1292 //================================================================
1293 bool GraphicsView_ViewPort::isSelectByRect() const
1295 return myAreSelectionPointsInitialized;
1298 //================================================================
1299 // Function : finishSelectByRect
1301 //================================================================
1302 void GraphicsView_ViewPort::finishSelectByRect()
1304 if( myAreSelectionPointsInitialized )
1313 myAreSelectionPointsInitialized = false;
1317 //================================================================
1318 // Function : selectionRect
1320 //================================================================
1321 QRect GraphicsView_ViewPort::selectionRect()
1324 if( myAreSelectionPointsInitialized )
1326 aRect.setLeft( qMin( myFirstSelectionPoint.x(), myLastSelectionPoint.x() ) );
1327 aRect.setTop( qMin( myFirstSelectionPoint.y(), myLastSelectionPoint.y() ) );
1328 aRect.setRight( qMax( myFirstSelectionPoint.x(), myLastSelectionPoint.x() ) );
1329 aRect.setBottom( qMax( myFirstSelectionPoint.y(), myLastSelectionPoint.y() ) );
1334 //================================================================
1335 // Function : prepareToSketch
1337 //================================================================
1338 void GraphicsView_ViewPort::prepareToSketch( bool theStatus )
1340 myIsPrepareToSketch = theStatus;
1342 setCursor( *getSketchCursor() );
1345 //================================================================
1346 // Function : isPrepareToSketch
1348 //================================================================
1349 bool GraphicsView_ViewPort::isPrepareToSketch()
1351 return myIsPrepareToSketch;
1354 //================================================================
1355 // Function : startSketching
1357 //================================================================
1358 void GraphicsView_ViewPort::startSketching( const QPointF& thePoint,
1361 prepareToSketch( false );
1363 if( !mySketchingItem )
1365 mySketchingItem = new QGraphicsPathItem();
1366 mySketchingItem->setZValue( SKETCH_Z_VALUE );
1368 QPen aPen = mySketchingItem->pen();
1369 aPen.setStyle( Qt::DotLine );
1370 mySketchingItem->setPen( aPen );
1372 addItem( mySketchingItem );
1375 mySketchingPoint = thePoint;
1378 aPath.moveTo( mySketchingPoint );
1379 mySketchingItem->setPath( aPath );
1380 mySketchingItem->setVisible( true );
1382 myIsSketching = true;
1383 myIsSketchingByPath = theIsPath;
1386 //================================================================
1387 // Function : drawSketching
1389 //================================================================
1390 void GraphicsView_ViewPort::drawSketching( const QPointF& thePoint )
1392 bool anIsPath = false;
1393 if( mySketchingItem && isSketching( &anIsPath ) )
1395 QPainterPath aPath = mySketchingItem->path();
1396 if( anIsPath ) // arbitrary path
1397 aPath.lineTo( thePoint );
1400 // make a valid rectangle
1401 double x1 = mySketchingPoint.x(), y1 = mySketchingPoint.y();
1402 double x2 = thePoint.x(), y2 = thePoint.y();
1403 QPointF aPoint1( qMin( x1, x2 ), qMin( y1, y2 ) );
1404 QPointF aPoint2( qMax( x1, x2 ), qMax( y1, y2 ) );
1405 QRectF aRect( aPoint1, aPoint2 );
1407 aPath = QPainterPath();
1408 aPath.addRect( aRect );
1410 mySketchingItem->setPath( aPath );
1414 //================================================================
1415 // Function : finishSketching
1417 //================================================================
1418 void GraphicsView_ViewPort::finishSketching( bool theStatus )
1420 prepareToSketch( false );
1422 mySketchingItem->setVisible( false );
1423 myIsSketching = false;
1425 setCursor( *getDefaultCursor() );
1429 QPainterPath aPath = mySketchingItem->path();
1430 emit vpSketchingFinished( aPath );
1434 //================================================================
1435 // Function : isSketching
1437 //================================================================
1438 bool GraphicsView_ViewPort::isSketching( bool* theIsPath ) const
1441 *theIsPath = myIsSketchingByPath;
1442 return myIsSketching;
1445 //================================================================
1446 // Function : dragObjects
1448 //================================================================
1449 void GraphicsView_ViewPort::dragObjects( QGraphicsSceneMouseEvent* e )
1451 GraphicsView_Object* anObject = getHighlightedObject();
1453 if( myDragPosition.isNull() )
1455 myDragPosition = e->scenePos();
1459 GraphicsView_ObjectList anObjectsToMove;
1460 if( anObject && anObject->isMovable() && ( e->buttons() & Qt::LeftButton ) )
1462 if( anObject->isSelected() )
1464 for( initSelected(); moreSelected(); nextSelected() )
1465 if( GraphicsView_Object* aMovingObject = selectedObject() )
1466 if( aMovingObject->isMovable() )
1467 anObjectsToMove.append( aMovingObject );
1470 anObjectsToMove.append( anObject );
1472 else if( hasInteractionFlag( DraggingByMiddleButton ) &&
1473 nbSelected() && ( e->buttons() & Qt::MidButton ) )
1475 for( initSelected(); moreSelected(); nextSelected() )
1476 if( GraphicsView_Object* aMovingObject = selectedObject() )
1477 if( aMovingObject->isMovable() )
1478 anObjectsToMove.append( aMovingObject );
1481 if( anObjectsToMove.isEmpty() )
1484 double aDX = e->scenePos().x() - myDragPosition.x();
1485 double aDY = e->scenePos().y() - myDragPosition.y();
1487 bool anIsMovingByXAllowed = true, anIsMovingByYAllowed = true;
1488 GraphicsView_ObjectListIterator anIter( anObjectsToMove );
1489 while( anIter.hasNext() )
1490 if( GraphicsView_Object* aMovingObject = anIter.next() )
1492 if( !aMovingObject->isMovingByXAllowed( aDX ) )
1493 anIsMovingByXAllowed = false;
1494 if( !aMovingObject->isMovingByYAllowed( aDY ) )
1495 anIsMovingByYAllowed = false;
1498 if( !anIsMovingByXAllowed && !anIsMovingByYAllowed )
1499 return; // myDragPosition shouldn't be changed
1501 if( !anIsMovingByXAllowed )
1504 if( !anIsMovingByYAllowed )
1507 anIter = anObjectsToMove;
1508 while( anIter.hasNext() )
1509 if( GraphicsView_Object* aMovingObject = anIter.next() )
1510 aMovingObject->move( aDX, aDY );
1512 if( anIsMovingByXAllowed )
1513 myDragPosition.setX( e->scenePos().x() );
1515 if( anIsMovingByYAllowed )
1516 myDragPosition.setY( e->scenePos().y() );
1519 //================================================================
1520 // Function : startPulling
1522 //================================================================
1523 bool GraphicsView_ViewPort::startPulling( const QPointF& thePoint )
1525 QListIterator<QGraphicsItem*> anIter( items() );
1526 while( anIter.hasNext() )
1528 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1530 QRectF aRect = anObject->getPullingRect();
1531 if( aRect.contains( thePoint ) && anObject->startPulling( thePoint ) )
1534 myPullingObject = anObject;
1535 //setCursor( *getHandCursor() ); // testing ImageViewer
1543 //================================================================
1544 // Function : drawPulling
1546 //================================================================
1547 void GraphicsView_ViewPort::drawPulling( const QPointF& thePoint )
1549 GraphicsView_Object* aLockedObject = 0;
1551 QListIterator<QGraphicsItem*> anIter( items() );
1552 while( anIter.hasNext() )
1554 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1556 if( !anObject->isVisible() )
1559 QRectF aRect = anObject->getPullingRect();
1560 if( aRect.contains( thePoint ) && anObject->portContains( thePoint ) )
1562 aLockedObject = anObject;
1568 myPullingObject->pull( thePoint, aLockedObject, getSelectedObjects() );
1571 //================================================================
1572 // Function : finishPulling
1574 //================================================================
1575 void GraphicsView_ViewPort::finishPulling( bool theStatus )
1577 myIsPulling = false;
1578 myPullingObject->finishPulling( theStatus, getSelectedObjects() );
1579 setCursor( *getDefaultCursor() );
1582 //================================================================
1583 // Function : cancelCurrentOperation
1585 //================================================================
1586 bool GraphicsView_ViewPort::cancelCurrentOperation()
1588 myIsHighlighting = false;
1592 for( initSelected(); moreSelected(); nextSelected() )
1593 if( GraphicsView_Object* aMovingObject = selectedObject() )
1594 aMovingObject->finishMove( false );
1596 if( GraphicsView_Object* aMovingObject = getHighlightedObject() )
1597 aMovingObject->finishMove( false );
1599 myIsDragging = false;
1600 myDragPosition = QPointF();
1601 //setCursor( myStoredCursor );
1602 setCursor( *getDefaultCursor() );
1609 finishPulling( false );
1613 if( isSketching() || isPrepareToSketch() )
1615 finishSketching( false );
1622 //================================================================
1623 // Function : onBoundingRectChanged
1625 //================================================================
1626 void GraphicsView_ViewPort::onBoundingRectChanged()
1628 if( hasInteractionFlag( TraceBoundingRect ) )
1630 QRectF aRect = objectsBoundingRect( true );
1631 myScene->setSceneRect( aRect.adjusted( -mySceneGap, -mySceneGap, mySceneGap, mySceneGap ) );
1635 //================================================================
1636 // Function : onKeyEvent
1638 //================================================================
1639 void GraphicsView_ViewPort::onKeyEvent( QKeyEvent* e )
1641 emit vpKeyEvent( e );
1644 //================================================================
1645 // Function : onMouseEvent
1647 //================================================================
1648 void GraphicsView_ViewPort::onMouseEvent( QGraphicsSceneMouseEvent* e )
1650 emit vpMouseEvent( e );
1652 bool anIsHandled = false;
1655 case QEvent::GraphicsSceneMousePress:
1657 if( hasInteractionFlag( EditFlags ) && nbSelected() )
1658 for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1659 if( GraphicsView_Object* anObject = selectedObject() )
1660 anIsHandled = anObject->handleMousePress( e );
1662 if( !anIsHandled && hasInteractionFlag( Dragging ) )
1664 bool anAccel = e->modifiers() & GraphicsView_ViewTransformer::accelKey();
1665 if( ( getHighlightedObject() &&
1666 getHighlightedObject()->isMovable() &&
1667 !( anAccel || e->button() != Qt::LeftButton ) ) ||
1668 ( hasInteractionFlag( DraggingByMiddleButton ) &&
1669 nbSelected() && !anAccel && e->button() == Qt::MidButton ) )
1671 myIsDragging = true;
1672 myStoredCursor = cursor();
1673 setCursor( Qt::ClosedHandCursor );
1678 case QEvent::GraphicsSceneMouseMove:
1680 if( hasInteractionFlag( EditFlags ) && nbSelected() )
1681 for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1682 if( GraphicsView_Object* anObject = selectedObject() )
1683 anIsHandled = anObject->handleMouseMove( e );
1685 if( !anIsHandled && !isPulling() && myIsDragging )
1689 case QEvent::GraphicsSceneMouseRelease:
1691 if( hasInteractionFlag( EditFlags ) && nbSelected() )
1692 for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1693 if( GraphicsView_Object* anObject = selectedObject() )
1694 anIsHandled = anObject->handleMouseRelease( e );
1696 if( !anIsHandled && !isPulling() && myIsDragging )
1698 emit vpObjectBeforeMoving();
1700 bool anIsMoved = false;
1701 for( initSelected(); moreSelected(); nextSelected() )
1702 if( GraphicsView_Object* aMovingObject = selectedObject() )
1703 anIsMoved = aMovingObject->finishMove( true ) || anIsMoved;
1705 if( GraphicsView_Object* aMovingObject = getHighlightedObject() )
1706 anIsMoved = aMovingObject->finishMove( true ) || anIsMoved;
1708 myIsDragging = false;
1709 myDragPosition = QPointF();
1710 setCursor( myStoredCursor );
1712 emit vpObjectAfterMoving( anIsMoved );
1716 case QEvent::GraphicsSceneMouseDoubleClick:
1717 break; // do nothing, just emit the signal
1722 if( myIsMousePositionEnabled )
1724 int aMouseX = (int)e->scenePos().x();
1725 int aMouseY = (int)e->scenePos().y();
1726 setViewLabelText( QString( "(%1, %2)" ).arg( aMouseX ).arg( aMouseY ) );
1730 //================================================================
1731 // Function : onWheelEvent
1733 //================================================================
1734 void GraphicsView_ViewPort::onWheelEvent( QGraphicsSceneWheelEvent* e )
1736 emit vpWheelEvent( e );
1739 //================================================================
1740 // Function : onContextMenuEvent
1742 //================================================================
1743 void GraphicsView_ViewPort::onContextMenuEvent( QGraphicsSceneContextMenuEvent* e )
1745 emit vpContextMenuEvent( e );
1748 //================================================================
1749 // Function : scrollContentsBy
1751 //================================================================
1752 void GraphicsView_ViewPort::scrollContentsBy( int theDX, int theDY )
1755 myViewLabel->setAcceptMoveEvents( false );
1757 QGraphicsView::scrollContentsBy( theDX, theDY );
1760 myViewLabel->setAcceptMoveEvents( true );