1 // Copyright (C) 2013-2016 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>
42 #define FOREGROUND_Z_VALUE -2
43 #define GRID_Z_VALUE -1
44 #define SKETCH_Z_VALUE 3000
46 int GraphicsView_ViewPort::nCounter = 0;
47 QCursor* GraphicsView_ViewPort::defCursor = 0;
48 QCursor* GraphicsView_ViewPort::handCursor = 0;
49 QCursor* GraphicsView_ViewPort::panCursor = 0;
50 QCursor* GraphicsView_ViewPort::panglCursor = 0;
51 QCursor* GraphicsView_ViewPort::zoomCursor = 0;
52 QCursor* GraphicsView_ViewPort::sketchCursor = 0;
54 //=======================================================================
55 // Name : GraphicsView_ViewPort::ViewLabel
56 // Purpose : Wrapper for label, which can ignore move events sent from
57 // QGraphicsView::scrollContentsBy() method, which,
58 // in its turn, called from GraphicsView_ViewPort::pan()
59 //=======================================================================
60 class GraphicsView_ViewPort::ViewLabel : public QLabel
63 ViewLabel( QWidget* theParent )
64 : QLabel( theParent ),
65 myAcceptMoveEvents( false )
70 void setAcceptMoveEvents( bool theFlag )
72 myAcceptMoveEvents = theFlag;
76 virtual void moveEvent( QMoveEvent* theEvent )
78 if( myAcceptMoveEvents )
79 QLabel::moveEvent( theEvent );
80 else // return the label to the initial position
82 myAcceptMoveEvents = true;
83 move( theEvent->oldPos() );
84 myAcceptMoveEvents = false;
89 bool myAcceptMoveEvents;
92 //================================================================
93 // Function : createCursors
95 //================================================================
96 void GraphicsView_ViewPort::createCursors ()
98 defCursor = new QCursor( Qt::ArrowCursor );
99 handCursor = new QCursor( Qt::PointingHandCursor );
100 panCursor = new QCursor( Qt::SizeAllCursor );
101 panglCursor = new QCursor( Qt::CrossCursor );
103 SUIT_ResourceMgr* rmgr = SUIT_Session::session()->resourceMgr();
104 zoomCursor = new QCursor( rmgr->loadPixmap( "GraphicsView", tr( "ICON_GV_CURSOR_ZOOM" ) ) );
106 sketchCursor = new QCursor( Qt::CrossCursor );
109 //================================================================
110 // Function : destroyCursors
112 //================================================================
113 void GraphicsView_ViewPort::destroyCursors()
115 delete defCursor; defCursor = 0;
116 delete handCursor; handCursor = 0;
117 delete panCursor; panCursor = 0;
118 delete panglCursor; panglCursor = 0;
119 delete zoomCursor; zoomCursor = 0;
120 delete sketchCursor; sketchCursor = 0;
123 //=======================================================================
124 // Name : GraphicsView_ViewPort
125 // Purpose : Constructor
126 //=======================================================================
127 GraphicsView_ViewPort::GraphicsView_ViewPort( QWidget* theParent )
128 : QGraphicsView( theParent ),
129 myInteractionFlags( 0 ),
131 myViewLabelPosition( VLP_None ),
132 myViewLabelLayout( 0 ),
133 myIsMousePositionEnabled( false ),
134 myForegroundItem( 0 ),
136 myIsTransforming( false ),
137 myHighlightedObject( 0 ),
140 myIsHighlighting( false ),
141 mySelectionIterator( 0 ),
143 myAreSelectionPointsInitialized( false ),
144 mySketchingItem( 0 ),
145 myIsPrepareToSketch( false ),
146 myIsSketching( false ),
147 myIsSketchingByPath( false ),
148 myIsDragging( false ),
149 myIsDragPositionInitialized( false ),
150 myIsPulling( false ),
151 myPullingObject( 0 ),
152 myStoredCursor( Qt::ArrowCursor )
155 myScene = new GraphicsView_Scene( this );
162 setInteractionFlags( EditFlags );
163 //setInteractionFlag( TraceBoundingRect );
164 //setInteractionFlag( DraggingByMiddleButton );
165 //setInteractionFlag( ImmediateContextMenu );
166 //setInteractionFlag( ImmediateSelection );
167 //setInteractionFlag( Sketching );
170 setBackgroundBrush( QBrush( Qt::white ) );
173 myIsForegroundEnabled = false;
174 myForegroundSize = QSizeF( 100, 30 );
175 myForegroundMargin = 0.0;
176 myForegroundColor = Qt::white;
177 myForegroundFrameColor = Qt::black;
178 myForegroundFrameLineWidth = 1.0;
181 myIsGridEnabled = false;
182 myGridCellSize = 100;
183 myGridLineStyle = Qt::DotLine;
184 myGridLineColor = Qt::darkGray;
186 // default index method (BspTreeIndex) leads to
187 // crashes in QGraphicsView::paintEvent() method
188 myScene->setItemIndexMethod( QGraphicsScene::NoIndex );
190 // render hints (default - TextAntialiasing only)
191 setRenderHints( QPainter::Antialiasing |
192 QPainter::TextAntialiasing |
193 QPainter::SmoothPixmapTransform |
194 QPainter::HighQualityAntialiasing );
196 connect( myScene, SIGNAL( gsKeyEvent( QKeyEvent* ) ),
197 this, SLOT( onKeyEvent( QKeyEvent* ) ) );
198 connect( myScene, SIGNAL( gsMouseEvent( QGraphicsSceneMouseEvent* ) ),
199 this, SLOT( onMouseEvent( QGraphicsSceneMouseEvent* ) ) );
200 connect( myScene, SIGNAL( gsWheelEvent( QGraphicsSceneWheelEvent* ) ),
201 this, SLOT( onWheelEvent( QGraphicsSceneWheelEvent* ) ) );
202 connect( myScene, SIGNAL( gsContextMenuEvent( QGraphicsSceneContextMenuEvent* ) ),
203 this, SLOT( onContextMenuEvent( QGraphicsSceneContextMenuEvent* ) ) );
205 connect( myScene, SIGNAL( gsBoundingRectChanged() ),
206 this, SLOT( onBoundingRectChanged() ) );
211 //=======================================================================
212 // Name : GraphicsView_ViewPort
213 // Purpose : Destructor
214 //=======================================================================
215 GraphicsView_ViewPort::~GraphicsView_ViewPort()
226 //================================================================
227 // Function : initialize
229 //================================================================
230 void GraphicsView_ViewPort::initialize()
232 if ( nCounter++ == 0 )
235 setMouseTracking( true );
236 setFocusPolicy( Qt::StrongFocus );
239 //================================================================
240 // Function : cleanup
242 //================================================================
243 void GraphicsView_ViewPort::cleanup()
245 if ( --nCounter == 0 )
249 //================================================================
250 // Function : addItem
252 //================================================================
253 void GraphicsView_ViewPort::addItem( QGraphicsItem* theItem )
255 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( theItem ) )
257 int aPriority = anObject->getPriority();
258 GraphicsView_ObjectList::iterator anIter, anIterEnd = myObjects.end();
259 for( anIter = myObjects.begin(); anIter != anIterEnd; anIter++ )
261 if( GraphicsView_Object* anObjectRef = *anIter )
263 if( anObjectRef->getPriority() > aPriority )
267 myObjects.insert( anIter, anObject );
268 anObject->setViewTransform( transform() );
269 anObject->addTo( this );
272 myScene->addItem( theItem );
273 onBoundingRectChanged();
276 //================================================================
277 // Function : isItemAdded
279 //================================================================
280 bool GraphicsView_ViewPort::isItemAdded( QGraphicsItem* theItem )
282 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( theItem ) )
284 for( GraphicsView_ObjectList::iterator anIter = myObjects.begin(); anIter != myObjects.end(); anIter++ )
285 if( theItem == *anIter )
289 for( int i = 0; i < myScene->items().size(); i++ )
290 if( theItem == myScene->items().at(i) )
296 //================================================================
297 // Function : removeItem
299 //================================================================
300 void GraphicsView_ViewPort::removeItem( QGraphicsItem* theItem )
302 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( theItem ) )
304 if( myHighlightedObject == anObject )
305 myHighlightedObject = 0;
306 mySelectedObjects.removeAll( anObject );
307 myObjects.removeAll( anObject );
308 anObject->removeFrom( this );
311 myScene->removeItem( theItem );
312 onBoundingRectChanged();
315 void GraphicsView_ViewPort::clearItems()
317 myHighlightedObject = 0;
318 mySelectedObjects.clear();
321 onBoundingRectChanged();
324 //================================================================
325 // Function : getObjects
327 //================================================================
328 GraphicsView_ObjectList GraphicsView_ViewPort::getObjects( SortType theSortType ) const
330 if( theSortType == SelectedFirst )
332 // to append selected objects after their non-selected siblings with similar priority
333 int aCurrentPriority = -1;
334 GraphicsView_ObjectList aSelectedObjects;
335 GraphicsView_ObjectList aTopmostObjects;
337 GraphicsView_ObjectList aList;
338 GraphicsView_ObjectListIterator anIter( myObjects );
339 while( anIter.hasNext() )
341 if( GraphicsView_Object* anObject = anIter.next() )
343 if( anObject->isOnTop() )
345 aTopmostObjects.append( anObject );
349 int aPriority = anObject->getPriority();
350 if( aPriority > aCurrentPriority )
352 if( !aSelectedObjects.isEmpty() )
354 aList.append( aSelectedObjects );
355 aSelectedObjects.clear();
357 aCurrentPriority = aPriority;
360 if( anObject->isSelected() )
361 aSelectedObjects.append( anObject );
363 aList.append( anObject );
367 // for selected objects with highest priority,
368 // which were not pushed to the result list yet
369 if( !aSelectedObjects.isEmpty() )
371 aList.append( aSelectedObjects );
372 aSelectedObjects.clear();
375 aList.append( aTopmostObjects );
380 if( theSortType == SortByZLevel ) // double loop, needs to be optimized
382 GraphicsView_ObjectList aList;
384 GraphicsView_ObjectListIterator anIter( myObjects );
385 while( anIter.hasNext() )
387 if( GraphicsView_Object* anObject = anIter.next() )
389 double aZValue = anObject->zValue();
390 GraphicsView_ObjectList::iterator anIter1, anIter1End = aList.end();
391 for( anIter1 = aList.begin(); anIter1 != anIter1End; anIter1++ )
392 if( GraphicsView_Object* anObjectRef = *anIter1 )
393 if( anObjectRef->zValue() > aZValue )
395 aList.insert( anIter1, anObject );
401 return myObjects; // theSortType == NoSorting
404 //================================================================
405 // Function : objectsBoundingRect
407 //================================================================
408 QRectF GraphicsView_ViewPort::objectsBoundingRect( bool theOnlyVisible ) const
411 QListIterator<QGraphicsItem*> anIter( items() );
412 while( anIter.hasNext() )
414 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
416 if( theOnlyVisible && !anObject->isVisible() )
419 QRectF anObjectRect = anObject->getRect();
420 if( !anObjectRect.isNull() )
423 aRect = anObject->getRect();
425 aRect |= anObject->getRect();
432 //================================================================
433 // Function : dumpView
435 //================================================================
436 QImage GraphicsView_ViewPort::dumpView( bool theWholeScene,
439 if( !theWholeScene ) // just grab the view contents
441 QPixmap aPixmap = QPixmap::grabWindow( viewport()->winId() );
442 return aPixmap.toImage();
445 // get a bounding rect of all presented objects
446 // (itemsBoundingRect() method is unsuitable)
447 QRectF aRect = objectsBoundingRect();
451 QRectF aTargetRect( 0, 0, aRect.width(), aRect.height() );
452 if( theSize.isValid() )
454 double aRatioX = theSize.width() / aTargetRect.width();
455 double aRatioY = theSize.height() / aTargetRect.height();
456 double aRatio = qMin( aRatioX, aRatioY );
457 aTargetRect.setWidth( aTargetRect.width() * aRatio );
458 aTargetRect.setHeight( aTargetRect.height() * aRatio );
461 // render the scene to an image
462 QImage anImage( aTargetRect.toRect().size(), QImage::Format_RGB32 );
463 QPainter aPainter( &anImage );
464 aPainter.setRenderHints( renderHints() );
466 myScene->render( &aPainter, aTargetRect, aRect );
471 bool GraphicsView_ViewPort::dumpViewToPSFormat(const QString& fileName)
473 QPrinter printer(QPrinter::ScreenResolution);
474 printer.setOutputFormat(QPrinter::PostScriptFormat);
475 printer.setOutputFileName(fileName);
477 if (!painter.begin(&printer))
480 QRect view( 0, 0, printer.pageRect().width(), printer.paperRect().height() );
481 QRectF bounds = myScene->itemsBoundingRect();
483 if( !view.isEmpty() && !bounds.isEmpty() )
485 float SCALE = 0.5;//qMin( view.width()/bounds.width(), view.height()/bounds.height() );
486 painter.setViewport( view );
487 painter.scale( SCALE, SCALE );
489 myScene->render( &painter, QRectF( view ), bounds );
496 //================================================================
497 // Function : setSceneGap
499 //================================================================
500 void GraphicsView_ViewPort::setSceneGap( double theSceneGap )
502 mySceneGap = theSceneGap;
503 onBoundingRectChanged();
506 //================================================================
507 // Function : setFitAllGap
509 //================================================================
510 void GraphicsView_ViewPort::setFitAllGap( double theFitAllGap )
512 myFitAllGap = theFitAllGap;
515 //================================================================
516 // Function : interactionFlags
518 //================================================================
519 int GraphicsView_ViewPort::interactionFlags() const
521 return myInteractionFlags;
524 //================================================================
525 // Function : hasInteractionFlag
527 //================================================================
528 bool GraphicsView_ViewPort::hasInteractionFlag( InteractionFlag theFlag )
530 return ( interactionFlags() & theFlag ) == theFlag;
533 //================================================================
534 // Function : setInteractionFlag
536 //================================================================
537 void GraphicsView_ViewPort::setInteractionFlag( InteractionFlag theFlag,
541 setInteractionFlags( myInteractionFlags | theFlag );
543 setInteractionFlags( myInteractionFlags & ~theFlag );
546 //================================================================
547 // Function : setInteractionFlags
549 //================================================================
550 void GraphicsView_ViewPort::setInteractionFlags( InteractionFlags theFlags )
552 myInteractionFlags = theFlags;
555 //================================================================
556 // Function : setViewLabelPosition
558 //================================================================
559 void GraphicsView_ViewPort::setViewLabelPosition( ViewLabelPosition thePosition,
562 if( theIsForced && !myViewLabel )
563 myViewLabel = new ViewLabel( viewport() );
568 if( thePosition == VLP_None )
570 myViewLabel->setVisible( false );
574 if( myViewLabelLayout )
575 delete myViewLabelLayout;
577 myViewLabelLayout = new QGridLayout( viewport() );
578 myViewLabelLayout->setMargin( 10 );
579 myViewLabelLayout->setSpacing( 0 );
581 int aRow = 0, aColumn = 0;
582 switch( thePosition )
584 case VLP_TopLeft: aRow = 0; aColumn = 0; break;
585 case VLP_TopRight: aRow = 0; aColumn = 1; break;
586 case VLP_BottomLeft: aRow = 1; aColumn = 0; break;
587 case VLP_BottomRight: aRow = 1; aColumn = 1; break;
591 myViewLabelLayout->addWidget( myViewLabel, aRow, aColumn );
592 myViewLabelLayout->setRowStretch( 1 - aRow, 1 );
593 myViewLabelLayout->setColumnStretch( 1 - aColumn, 1 );
595 myViewLabel->setVisible( true );
598 //================================================================
599 // Function : setViewLabelText
601 //================================================================
602 void GraphicsView_ViewPort::setViewLabelText( const QString& theText )
605 myViewLabel->setText( theText );
608 //================================================================
609 // Function : setMousePositionEnabled
611 //================================================================
612 void GraphicsView_ViewPort::setMousePositionEnabled( bool theState )
614 myIsMousePositionEnabled = theState;
618 setViewLabelPosition( VLP_BottomLeft, true );
620 int aMouseX = 0, aMouseY = 0;
621 setViewLabelText( QString( "(%1, %2)" ).arg( aMouseX ).arg( aMouseY ) );
624 setViewLabelPosition( VLP_None );
627 //================================================================
628 // Function : backgroundColor
630 //================================================================
631 QColor GraphicsView_ViewPort::backgroundColor() const
633 return backgroundBrush().color();
636 //================================================================
637 // Function : setBackgroundColor
639 //================================================================
640 void GraphicsView_ViewPort::setBackgroundColor( const QColor& theColor )
642 setBackgroundBrush( QBrush( theColor ) );
645 //================================================================
646 // Function : setForegroundEnabled
648 //================================================================
649 void GraphicsView_ViewPort::setForegroundEnabled( bool theState )
651 myIsForegroundEnabled = theState;
654 //================================================================
655 // Function : setForegroundSize
657 //================================================================
658 void GraphicsView_ViewPort::setForegroundSize( const QSizeF& theSize )
660 myForegroundSize = theSize;
663 //================================================================
664 // Function : setForegroundMargin
666 //================================================================
667 void GraphicsView_ViewPort::setForegroundMargin( double theMargin )
669 myForegroundMargin = theMargin;
672 //================================================================
673 // Function : setForegroundColor
675 //================================================================
676 void GraphicsView_ViewPort::setForegroundColor( const QColor& theColor )
678 myForegroundColor = theColor;
681 //================================================================
682 // Function : setForegroundFrameColor
684 //================================================================
685 void GraphicsView_ViewPort::setForegroundFrameColor( const QColor& theColor )
687 myForegroundFrameColor = theColor;
690 //================================================================
691 // Function : setForegroundFrameLineWidth
693 //================================================================
694 void GraphicsView_ViewPort::setForegroundFrameLineWidth( double theLineWidth )
696 myForegroundFrameLineWidth = theLineWidth;
699 //================================================================
700 // Function : updateForeground
702 //================================================================
703 void GraphicsView_ViewPort::updateForeground()
705 if( myIsForegroundEnabled )
707 if( !myForegroundItem )
708 myForegroundItem = myScene->addRect( QRectF(), QPen(), QBrush( Qt::white ) );
709 myForegroundItem->setZValue( FOREGROUND_Z_VALUE );
711 QPointF aPoint = QPointF();
712 QRectF aRect( aPoint, myForegroundSize );
713 aRect.adjust( -myForegroundMargin, -myForegroundMargin,
714 myForegroundMargin, myForegroundMargin );
715 myForegroundItem->setRect( aRect );
717 QBrush aBrush = myForegroundItem->brush();
718 aBrush.setColor( myForegroundColor );
719 myForegroundItem->setBrush( aBrush );
721 QPen aPen = myForegroundItem->pen();
722 aPen.setColor( myForegroundFrameColor );
723 aPen.setWidthF( myForegroundFrameLineWidth );
724 myForegroundItem->setPen( aPen );
726 myForegroundItem->setVisible( true );
728 myScene->setSceneRect( aRect.adjusted( -mySceneGap, -mySceneGap, mySceneGap, mySceneGap ) );
732 if( myForegroundItem )
733 myForegroundItem->setVisible( false );
736 updateGrid(); // foreground size could be changed
739 //================================================================
740 // Function : setGridEnabled
742 //================================================================
743 void GraphicsView_ViewPort::setGridEnabled( bool theState )
745 myIsGridEnabled = theState;
748 //================================================================
749 // Function : setGridCellSize
751 //================================================================
752 void GraphicsView_ViewPort::setGridCellSize( int theCellSize )
754 myGridCellSize = theCellSize;
757 //================================================================
758 // Function : setGridLineStyle
760 //================================================================
761 void GraphicsView_ViewPort::setGridLineStyle( int theLineStyle )
763 myGridLineStyle = theLineStyle;
766 //================================================================
767 // Function : setGridLineColor
769 //================================================================
770 void GraphicsView_ViewPort::setGridLineColor( const QColor& theLineColor )
772 myGridLineColor = theLineColor;
775 //================================================================
776 // Function : updateGrid
778 //================================================================
779 void GraphicsView_ViewPort::updateGrid()
781 if( myIsGridEnabled )
784 myGridItem = myScene->addPath( QPainterPath() );
785 myGridItem->setZValue( GRID_Z_VALUE );
787 double aWidth = myForegroundSize.width();
788 double aHeight = myForegroundSize.height();
790 int aGridNbX = int( aWidth / myGridCellSize ) + 1;
791 int aGridNbY = int( aHeight / myGridCellSize ) + 1;
795 for( anIndex = 0; anIndex < aGridNbX; anIndex++ )
797 double x = myGridCellSize * (double)anIndex;
798 aPath.moveTo( x, 0 );
799 aPath.lineTo( x, aHeight );
801 for( anIndex = 0; anIndex < aGridNbY; anIndex++ )
803 double y = myGridCellSize * (double)anIndex;
804 aPath.moveTo( 0, y );
805 aPath.lineTo( aWidth, y );
807 myGridItem->setPath( aPath );
809 QPen aPen = myGridItem->pen();
810 aPen.setStyle( (Qt::PenStyle)myGridLineStyle );
811 aPen.setColor( myGridLineColor );
812 myGridItem->setPen( aPen );
814 myGridItem->setVisible( true );
819 myGridItem->setVisible( false );
823 //================================================================
826 //================================================================
827 void GraphicsView_ViewPort::reset()
832 //================================================================
835 //================================================================
836 void GraphicsView_ViewPort::pan( double theDX, double theDY )
838 myIsTransforming = true;
841 myViewLabel->setAcceptMoveEvents( false );
843 if( QScrollBar* aHBar = horizontalScrollBar() )
844 aHBar->setValue( aHBar->value() - theDX );
845 if( QScrollBar* aVBar = verticalScrollBar() )
846 aVBar->setValue( aVBar->value() + theDY );
849 myViewLabel->setAcceptMoveEvents( true );
851 myIsTransforming = false;
856 //================================================================
857 // Function : setCenter
859 //================================================================
860 void GraphicsView_ViewPort::setCenter( double theX, double theY )
862 myIsTransforming = true;
864 setTransform( myCurrentTransform );
865 centerOn( theX, theY );
867 myIsTransforming = false;
872 //================================================================
875 //================================================================
876 void GraphicsView_ViewPort::zoom( double theX1, double theY1, double theX2, double theY2 )
878 myIsTransforming = true;
880 double aDX = theX2 - theX1;
881 double aDY = theY2 - theY1;
882 double aZoom = sqrt( aDX * aDX + aDY * aDY ) / 100 + 1;
883 aZoom = ( aDX > 0 ) ? aZoom : 1 / aZoom;
885 QTransform aTransform = transform();
886 aTransform.scale( aZoom, aZoom );
887 double aM11 = aTransform.m11();
888 double aM22 = aTransform.m22();
889 // increasing of diagonal coefficients (>300) leads to a crash sometimes
890 // at the values of 100 some primitives are drawn incorrectly
891 if( qMax( aM11, aM22 ) < 100 )
892 setTransform( aTransform );
894 myIsTransforming = false;
899 //================================================================
900 // Function : fitRect
902 //================================================================
903 void GraphicsView_ViewPort::fitRect( const QRectF& theRect )
905 myIsTransforming = true;
907 fitInView( theRect, Qt::KeepAspectRatio );
909 myIsTransforming = false;
914 //================================================================
915 // Function : fitSelect
917 //================================================================
918 void GraphicsView_ViewPort::fitSelect()
920 myIsTransforming = true;
923 for( initSelected(); moreSelected(); nextSelected() )
925 if( GraphicsView_Object* aMovingObject = selectedObject() )
927 QRectF aRect = aMovingObject->getRect();
928 if( aGlobalRect.isNull() )
931 aGlobalRect |= aRect;
935 if( !aGlobalRect.isNull() )
937 double aGap = qMax( aGlobalRect.width(), aGlobalRect.height() ) / 5;
938 aGlobalRect.adjust( -aGap, -aGap, aGap, aGap );
939 fitInView( aGlobalRect, Qt::KeepAspectRatio );
942 myIsTransforming = false;
947 //================================================================
950 //================================================================
951 void GraphicsView_ViewPort::fitAll( bool theKeepScale )
953 myIsTransforming = true;
956 myCurrentTransform = transform();
958 double aGap = myFitAllGap;
959 QRectF aRect = objectsBoundingRect( true );
960 fitInView( aRect.adjusted( -aGap, -aGap, aGap, aGap ), Qt::KeepAspectRatio );
962 myIsTransforming = false;
967 //================================================================
968 // Function : fitWidth
970 //================================================================
971 void GraphicsView_ViewPort::fitWidth()
973 myIsTransforming = true;
975 double aGap = myFitAllGap;
976 QRectF aRect = objectsBoundingRect( true );
978 double aTop = aRect.top();
979 double aLeft = aRect.left();
982 aRect.setY( aRect.center().y() );
983 aRect.setHeight( aMargin );
985 fitInView( aRect.adjusted( -aGap, -aGap, aGap, aGap ), Qt::KeepAspectRatio );
986 ensureVisible( aLeft, aTop, aMargin, aMargin, 0, aGap );
988 myIsTransforming = false;
993 //================================================================
994 // Function : applyTransform
996 //================================================================
997 void GraphicsView_ViewPort::applyTransform()
999 GraphicsView_ObjectListIterator anIter( getObjects() );
1000 while( anIter.hasNext() )
1001 if( GraphicsView_Object* anObject = anIter.next() )
1002 anObject->setViewTransform( transform() );
1005 //================================================================
1006 // Function : currentBlock
1008 //================================================================
1009 GraphicsView_ViewPort::BlockStatus GraphicsView_ViewPort::currentBlock()
1011 if( isDragging() && !myDragPosition.isNull() )
1012 return BlockStatus( BS_Selection );
1014 if( myAreSelectionPointsInitialized && ( myFirstSelectionPoint != myLastSelectionPoint ) )
1015 return BlockStatus( BS_Selection );
1018 return BlockStatus( BS_Selection );
1023 //================================================================
1024 // Function : highlight
1026 //================================================================
1027 void GraphicsView_ViewPort::highlight( double theX, double theY )
1029 myIsHighlighting = true;
1030 myHighlightX = theX;
1031 myHighlightY = theY;
1033 bool anIsHighlighted = false;
1034 bool anIsOnObject = false;
1036 GraphicsView_Object* aPreviousHighlightedObject = myHighlightedObject;
1037 GraphicsView_Object* aHighlightedObject = 0;
1041 GraphicsView_ObjectList aList = getObjects( SortByZLevel );
1042 GraphicsView_ObjectListIterator anIter( aList );
1043 anIter.toBack(); // objects with higher priority have to be checked earlier
1044 while( anIter.hasPrevious() )
1046 if( GraphicsView_Object* anObject = anIter.previous() )
1048 if( anObject->isVisible() && anObject->isSelectable() )
1050 if( anObject->checkHighlight( theX, theY, aCursor ) )
1052 anIsOnObject = true;
1053 anIsHighlighted = anObject->highlight( theX, theY );
1056 if( anIsHighlighted )
1058 aHighlightedObject = anObject;
1065 setCursor( aCursor );
1070 while( anIter.hasNext() )
1071 if( GraphicsView_Object* anObject = anIter.next() )
1072 anObject->unhighlight();
1074 myHighlightedObject = 0;
1077 else if( !myHighlightedObject && anIsHighlighted )
1079 myHighlightedObject = aHighlightedObject;
1081 else if( myHighlightedObject && !anIsHighlighted )
1083 myHighlightedObject->unhighlight();
1084 myHighlightedObject = 0;
1086 else if( myHighlightedObject && anIsHighlighted )
1088 myHighlightedObject->highlight( theX, theY );
1089 if( myHighlightedObject != aHighlightedObject )
1091 myHighlightedObject->unhighlight();
1092 myHighlightedObject = aHighlightedObject;
1097 //================================================================
1098 // Function : clearHighlighted
1100 //================================================================
1101 void GraphicsView_ViewPort::clearHighlighted()
1103 if( myHighlightedObject )
1105 myHighlightedObject->unhighlight();
1106 myHighlightedObject = 0;
1110 //================================================================
1111 // Function : select
1113 //================================================================
1114 int GraphicsView_ViewPort::select( const QRectF& theRect, bool theIsAppend )
1116 if( !myIsHighlighting )
1117 return GVSS_NoChanged;
1119 GV_SelectionStatus aStatus = GVSS_Invalid;
1120 if( theRect.isNull() ) // point selection
1122 if( myHighlightedObject )
1124 if( mySelectedObjects.count() == 1 &&
1125 mySelectedObjects.first() == myHighlightedObject )
1126 aStatus = GVSS_LocalChanged;
1130 GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1131 while( anIter.hasNext() )
1132 if( GraphicsView_Object* anObject = anIter.next() )
1133 if( myHighlightedObject != anObject )
1134 anObject->unselect();
1136 if( !mySelectedObjects.isEmpty() && aStatus == GVSS_Invalid )
1137 aStatus = GVSS_GlobalChanged;
1138 mySelectedObjects.clear();
1140 else if( myHighlightedObject->isSelected() && aStatus != GVSS_LocalChanged )
1142 mySelectedObjects.removeAll( myHighlightedObject );
1143 myHighlightedObject->unselect();
1145 if( !mySelectedObjects.isEmpty() && aStatus == GVSS_Invalid )
1146 aStatus = GVSS_GlobalChanged;
1151 if( myHighlightedObject->select( myHighlightX, myHighlightY, QRectF() ) &&
1152 mySelectedObjects.indexOf( myHighlightedObject ) == -1 )
1154 mySelectedObjects.append( myHighlightedObject );
1155 if( aStatus == GVSS_Invalid )
1156 aStatus = GVSS_GlobalChanged;
1158 else if( aStatus == GVSS_LocalChanged )
1159 aStatus = GVSS_GlobalChanged;
1164 if( !myHighlightedObject )
1168 GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1169 while( anIter.hasNext() )
1170 if( GraphicsView_Object* anObject = anIter.next() )
1171 if( myHighlightedObject != anObject )
1172 anObject->unselect();
1174 if( !mySelectedObjects.isEmpty() )
1175 aStatus = GVSS_GlobalChanged;
1176 mySelectedObjects.clear();
1181 return GVSS_NoChanged;
1183 else // rectangle selection
1185 aStatus = GVSS_NoChanged;
1187 bool updateAll = false;
1190 if( !mySelectedObjects.isEmpty() )
1191 aStatus = GVSS_GlobalChanged;
1193 GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1194 while( anIter.hasNext() )
1195 if( GraphicsView_Object* anObject = anIter.next() )
1196 if( myHighlightedObject != anObject )
1197 anObject->unselect();
1198 mySelectedObjects.clear();
1201 QListIterator<QGraphicsItem*> anIter( items() );
1202 while( anIter.hasNext() )
1204 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1206 if( anObject->isVisible() && anObject->isSelectable() )
1208 bool anIsSelected = false;
1209 QRectF aRect = anObject->getRect();
1210 if( theRect.contains( aRect ) && myIsHighlighting )
1211 anIsSelected = anObject->select( myHighlightX, myHighlightY, theRect );
1213 if( anIsSelected && mySelectedObjects.indexOf( anObject ) == -1 )
1215 mySelectedObjects.append( anObject );
1216 aStatus = GVSS_GlobalChanged;
1225 //================================================================
1226 // Function : clearSelected
1228 //================================================================
1229 void GraphicsView_ViewPort::clearSelected()
1231 GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1232 while( anIter.hasNext() )
1233 if( GraphicsView_Object* anObject = anIter.next() )
1234 anObject->unselect();
1235 mySelectedObjects.clear();
1238 //================================================================
1239 // Function : setSelected
1241 //================================================================
1242 void GraphicsView_ViewPort::setSelected( GraphicsView_Object* theObject )
1246 theObject->setSelected( true );
1247 mySelectedObjects.append( theObject );
1251 //================================================================
1252 // Function : nbSelected
1254 //================================================================
1255 int GraphicsView_ViewPort::nbSelected() const
1257 return mySelectedObjects.count();
1260 //================================================================
1261 // Function : initSelected
1263 //================================================================
1264 void GraphicsView_ViewPort::initSelected()
1266 mySelectionIterator = 0;
1269 //================================================================
1270 // Function : moreSelected
1272 //================================================================
1273 bool GraphicsView_ViewPort::moreSelected()
1275 return mySelectionIterator < nbSelected();
1278 //================================================================
1279 // Function : nextSelected
1281 //================================================================
1282 bool GraphicsView_ViewPort::nextSelected()
1284 if( mySelectionIterator >= 0 && mySelectionIterator < nbSelected() )
1286 mySelectionIterator++;
1292 //================================================================
1293 // Function : selectedObject
1295 //================================================================
1296 GraphicsView_Object* GraphicsView_ViewPort::selectedObject()
1298 if( mySelectionIterator >= 0 && mySelectionIterator < nbSelected() )
1299 return mySelectedObjects[ mySelectionIterator ];
1303 //================================================================
1304 // Function : startSelectByRect
1306 //================================================================
1307 void GraphicsView_ViewPort::startSelectByRect( int x, int y )
1309 if( !myAreSelectionPointsInitialized )
1311 myFirstSelectionPoint = QPoint( x, y );
1312 myLastSelectionPoint = QPoint( x, y );
1313 myAreSelectionPointsInitialized = true;
1318 myRectBand = new QRubberBand( QRubberBand::Rectangle, this );
1320 palette.setColor( myRectBand->foregroundRole(), Qt::white );
1321 myRectBand->setPalette( palette );
1326 //================================================================
1327 // Function : drawSelectByRect
1329 //================================================================
1330 void GraphicsView_ViewPort::drawSelectByRect( int x, int y )
1332 if( myAreSelectionPointsInitialized )
1336 myLastSelectionPoint.setX( x );
1337 myLastSelectionPoint.setY( y );
1339 QRect aRect = selectionRect();
1340 myRectBand->setGeometry( aRect );
1341 myRectBand->setVisible( aRect.isValid() );
1345 //================================================================
1346 // Function : isSelectByRect
1348 //================================================================
1349 bool GraphicsView_ViewPort::isSelectByRect() const
1351 return myAreSelectionPointsInitialized;
1354 //================================================================
1355 // Function : finishSelectByRect
1357 //================================================================
1358 void GraphicsView_ViewPort::finishSelectByRect()
1360 if( myAreSelectionPointsInitialized )
1369 myAreSelectionPointsInitialized = false;
1373 //================================================================
1374 // Function : selectionRect
1376 //================================================================
1377 QRect GraphicsView_ViewPort::selectionRect()
1380 if( myAreSelectionPointsInitialized )
1382 aRect.setLeft( qMin( myFirstSelectionPoint.x(), myLastSelectionPoint.x() ) );
1383 aRect.setTop( qMin( myFirstSelectionPoint.y(), myLastSelectionPoint.y() ) );
1384 aRect.setRight( qMax( myFirstSelectionPoint.x(), myLastSelectionPoint.x() ) );
1385 aRect.setBottom( qMax( myFirstSelectionPoint.y(), myLastSelectionPoint.y() ) );
1390 //================================================================
1391 // Function : prepareToSketch
1393 //================================================================
1394 void GraphicsView_ViewPort::prepareToSketch( bool theStatus )
1396 myIsPrepareToSketch = theStatus;
1398 setCursor( *getSketchCursor() );
1401 //================================================================
1402 // Function : isPrepareToSketch
1404 //================================================================
1405 bool GraphicsView_ViewPort::isPrepareToSketch()
1407 return myIsPrepareToSketch;
1410 //================================================================
1411 // Function : startSketching
1413 //================================================================
1414 void GraphicsView_ViewPort::startSketching( const QPointF& thePoint,
1417 prepareToSketch( false );
1419 if( !mySketchingItem )
1421 mySketchingItem = new QGraphicsPathItem();
1422 mySketchingItem->setZValue( SKETCH_Z_VALUE );
1424 QPen aPen = mySketchingItem->pen();
1425 aPen.setStyle( Qt::DotLine );
1426 mySketchingItem->setPen( aPen );
1428 addItem( mySketchingItem );
1431 mySketchingPoint = thePoint;
1434 aPath.moveTo( mySketchingPoint );
1435 mySketchingItem->setPath( aPath );
1436 mySketchingItem->setVisible( true );
1438 myIsSketching = true;
1439 myIsSketchingByPath = theIsPath;
1442 //================================================================
1443 // Function : drawSketching
1445 //================================================================
1446 void GraphicsView_ViewPort::drawSketching( const QPointF& thePoint )
1448 bool anIsPath = false;
1449 if( mySketchingItem && isSketching( &anIsPath ) )
1451 QPainterPath aPath = mySketchingItem->path();
1452 if( anIsPath ) // arbitrary path
1453 aPath.lineTo( thePoint );
1456 // make a valid rectangle
1457 double x1 = mySketchingPoint.x(), y1 = mySketchingPoint.y();
1458 double x2 = thePoint.x(), y2 = thePoint.y();
1459 QPointF aPoint1( qMin( x1, x2 ), qMin( y1, y2 ) );
1460 QPointF aPoint2( qMax( x1, x2 ), qMax( y1, y2 ) );
1461 QRectF aRect( aPoint1, aPoint2 );
1463 aPath = QPainterPath();
1464 aPath.addRect( aRect );
1466 mySketchingItem->setPath( aPath );
1470 //================================================================
1471 // Function : finishSketching
1473 //================================================================
1474 void GraphicsView_ViewPort::finishSketching( bool theStatus )
1476 prepareToSketch( false );
1478 mySketchingItem->setVisible( false );
1479 myIsSketching = false;
1481 setCursor( *getDefaultCursor() );
1485 QPainterPath aPath = mySketchingItem->path();
1486 emit vpSketchingFinished( aPath );
1490 //================================================================
1491 // Function : isSketching
1493 //================================================================
1494 bool GraphicsView_ViewPort::isSketching( bool* theIsPath ) const
1497 *theIsPath = myIsSketchingByPath;
1498 return myIsSketching;
1501 //================================================================
1502 // Function : dragObjects
1504 //================================================================
1505 void GraphicsView_ViewPort::dragObjects( QGraphicsSceneMouseEvent* e )
1507 GraphicsView_Object* anObject = getHighlightedObject();
1509 if( myDragPosition.isNull() )
1511 myDragPosition = e->scenePos();
1515 GraphicsView_ObjectList anObjectsToMove;
1516 if( anObject && anObject->isMovable() && ( e->buttons() & Qt::LeftButton ) )
1518 if( anObject->isSelected() )
1520 for( initSelected(); moreSelected(); nextSelected() )
1521 if( GraphicsView_Object* aMovingObject = selectedObject() )
1522 if( aMovingObject->isMovable() )
1523 anObjectsToMove.append( aMovingObject );
1526 anObjectsToMove.append( anObject );
1528 else if( hasInteractionFlag( DraggingByMiddleButton ) &&
1529 nbSelected() && ( e->buttons() & Qt::MidButton ) )
1531 for( initSelected(); moreSelected(); nextSelected() )
1532 if( GraphicsView_Object* aMovingObject = selectedObject() )
1533 if( aMovingObject->isMovable() )
1534 anObjectsToMove.append( aMovingObject );
1537 if( anObjectsToMove.isEmpty() )
1540 double aDX = e->scenePos().x() - myDragPosition.x();
1541 double aDY = e->scenePos().y() - myDragPosition.y();
1543 bool anIsMovingByXAllowed = true, anIsMovingByYAllowed = true;
1544 GraphicsView_ObjectListIterator anIter( anObjectsToMove );
1545 while( anIter.hasNext() )
1546 if( GraphicsView_Object* aMovingObject = anIter.next() )
1548 if( !aMovingObject->isMovingByXAllowed( aDX ) )
1549 anIsMovingByXAllowed = false;
1550 if( !aMovingObject->isMovingByYAllowed( aDY ) )
1551 anIsMovingByYAllowed = false;
1554 if( !anIsMovingByXAllowed && !anIsMovingByYAllowed )
1555 return; // myDragPosition shouldn't be changed
1557 if( !anIsMovingByXAllowed )
1560 if( !anIsMovingByYAllowed )
1563 anIter = anObjectsToMove;
1564 while( anIter.hasNext() )
1565 if( GraphicsView_Object* aMovingObject = anIter.next() )
1566 aMovingObject->move( aDX, aDY );
1568 if( anIsMovingByXAllowed )
1569 myDragPosition.setX( e->scenePos().x() );
1571 if( anIsMovingByYAllowed )
1572 myDragPosition.setY( e->scenePos().y() );
1575 //================================================================
1576 // Function : startPulling
1578 //================================================================
1579 bool GraphicsView_ViewPort::startPulling( const QPointF& thePoint )
1581 QListIterator<QGraphicsItem*> anIter( items() );
1582 while( anIter.hasNext() )
1584 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1586 QRectF aRect = anObject->getPullingRect();
1587 if( aRect.contains( thePoint ) && anObject->startPulling( thePoint ) )
1590 myPullingObject = anObject;
1591 //setCursor( *getHandCursor() ); // testing ImageViewer
1599 //================================================================
1600 // Function : drawPulling
1602 //================================================================
1603 void GraphicsView_ViewPort::drawPulling( const QPointF& thePoint )
1605 GraphicsView_Object* aLockedObject = 0;
1607 QListIterator<QGraphicsItem*> anIter( items() );
1608 while( anIter.hasNext() )
1610 if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1612 if( !anObject->isVisible() )
1615 QRectF aRect = anObject->getPullingRect();
1616 if( aRect.contains( thePoint ) && anObject->portContains( thePoint ) )
1618 aLockedObject = anObject;
1624 myPullingObject->pull( thePoint, aLockedObject, getSelectedObjects() );
1627 //================================================================
1628 // Function : finishPulling
1630 //================================================================
1631 void GraphicsView_ViewPort::finishPulling( bool theStatus )
1633 myIsPulling = false;
1634 myPullingObject->finishPulling( theStatus, getSelectedObjects() );
1635 setCursor( *getDefaultCursor() );
1638 //================================================================
1639 // Function : cancelCurrentOperation
1641 //================================================================
1642 bool GraphicsView_ViewPort::cancelCurrentOperation()
1644 myIsHighlighting = false;
1648 for( initSelected(); moreSelected(); nextSelected() )
1649 if( GraphicsView_Object* aMovingObject = selectedObject() )
1650 aMovingObject->finishMove( false );
1652 if( GraphicsView_Object* aMovingObject = getHighlightedObject() )
1653 aMovingObject->finishMove( false );
1655 myIsDragging = false;
1656 myDragPosition = QPointF();
1657 //setCursor( myStoredCursor );
1658 setCursor( *getDefaultCursor() );
1665 finishPulling( false );
1669 if( isSketching() || isPrepareToSketch() )
1671 finishSketching( false );
1678 //================================================================
1679 // Function : onBoundingRectChanged
1681 //================================================================
1682 void GraphicsView_ViewPort::onBoundingRectChanged()
1684 if( hasInteractionFlag( TraceBoundingRect ) )
1686 QRectF aRect = objectsBoundingRect( true );
1687 myScene->setSceneRect( aRect.adjusted( -mySceneGap, -mySceneGap, mySceneGap, mySceneGap ) );
1691 //================================================================
1692 // Function : onKeyEvent
1694 //================================================================
1695 void GraphicsView_ViewPort::onKeyEvent( QKeyEvent* e )
1697 emit vpKeyEvent( e );
1700 //================================================================
1701 // Function : onMouseEvent
1703 //================================================================
1704 void GraphicsView_ViewPort::onMouseEvent( QGraphicsSceneMouseEvent* e )
1706 emit vpMouseEvent( e );
1708 bool anIsHandled = false;
1711 case QEvent::GraphicsSceneMousePress:
1713 if( hasInteractionFlag( EditFlags ) && nbSelected() )
1714 for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1715 if( GraphicsView_Object* anObject = selectedObject() )
1716 anIsHandled = anObject->handleMousePress( e );
1718 if( !anIsHandled && hasInteractionFlag( Dragging ) )
1720 bool anAccel = e->modifiers() & GraphicsView_ViewTransformer::accelKey();
1721 if( ( getHighlightedObject() &&
1722 getHighlightedObject()->isMovable() &&
1723 !( anAccel || e->button() != Qt::LeftButton ) ) ||
1724 ( hasInteractionFlag( DraggingByMiddleButton ) &&
1725 nbSelected() && !anAccel && e->button() == Qt::MidButton ) )
1727 myIsDragging = true;
1728 myStoredCursor = cursor();
1729 setCursor( Qt::ClosedHandCursor );
1734 case QEvent::GraphicsSceneMouseMove:
1736 if( hasInteractionFlag( EditFlags ) && nbSelected() )
1737 for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1738 if( GraphicsView_Object* anObject = selectedObject() )
1739 anIsHandled = anObject->handleMouseMove( e );
1741 if( !anIsHandled && !isPulling() && myIsDragging )
1745 case QEvent::GraphicsSceneMouseRelease:
1747 if( hasInteractionFlag( EditFlags ) && nbSelected() )
1748 for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1749 if( GraphicsView_Object* anObject = selectedObject() )
1750 anIsHandled = anObject->handleMouseRelease( e );
1752 if( !anIsHandled && !isPulling() && myIsDragging )
1754 emit vpObjectBeforeMoving();
1756 bool anIsMoved = false;
1757 for( initSelected(); moreSelected(); nextSelected() )
1758 if( GraphicsView_Object* aMovingObject = selectedObject() )
1759 anIsMoved = aMovingObject->finishMove( true ) || anIsMoved;
1761 if( GraphicsView_Object* aMovingObject = getHighlightedObject() )
1762 anIsMoved = aMovingObject->finishMove( true ) || anIsMoved;
1764 myIsDragging = false;
1765 myDragPosition = QPointF();
1766 setCursor( myStoredCursor );
1768 emit vpObjectAfterMoving( anIsMoved );
1772 case QEvent::GraphicsSceneMouseDoubleClick:
1773 break; // do nothing, just emit the signal
1778 if( myIsMousePositionEnabled )
1780 int aMouseX = (int)e->scenePos().x();
1781 int aMouseY = (int)e->scenePos().y();
1782 setViewLabelText( QString( "(%1, %2)" ).arg( aMouseX ).arg( aMouseY ) );
1786 //================================================================
1787 // Function : onWheelEvent
1789 //================================================================
1790 void GraphicsView_ViewPort::onWheelEvent( QGraphicsSceneWheelEvent* e )
1792 emit vpWheelEvent( e );
1795 //================================================================
1796 // Function : onContextMenuEvent
1798 //================================================================
1799 void GraphicsView_ViewPort::onContextMenuEvent( QGraphicsSceneContextMenuEvent* e )
1801 emit vpContextMenuEvent( e );
1804 //================================================================
1805 // Function : scrollContentsBy
1807 //================================================================
1808 void GraphicsView_ViewPort::scrollContentsBy( int theDX, int theDY )
1811 myViewLabel->setAcceptMoveEvents( false );
1813 QGraphicsView::scrollContentsBy( theDX, theDY );
1816 myViewLabel->setAcceptMoveEvents( true );