Salome HOME
Merge modifications for HYDRO project (origin/hydro/imps_2017 branch)
[modules/gui.git] / src / GraphicsView / GraphicsView_ViewPort.cxx
1 // Copyright (C) 2013-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "GraphicsView_ViewPort.h"
21
22 #include "GraphicsView_Object.h"
23 #include "GraphicsView_Scene.h"
24 #include "GraphicsView_ViewTransformer.h"
25
26 #include "SUIT_ResourceMgr.h"
27 #include "SUIT_Session.h"
28
29 #include <QCursor>
30 #include <QGraphicsSceneMouseEvent>
31 #include <QGridLayout>
32 #include <QLabel>
33 #include <QMoveEvent>
34 #include <QRectF>
35 #include <QRubberBand>
36 #include <QScrollBar>
37
38 #include <math.h>
39
40 #define FOREGROUND_Z_VALUE -2
41 #define GRID_Z_VALUE       -1
42 #define SKETCH_Z_VALUE     3000
43
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;
51
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
59 {
60 public:
61   ViewLabel( QWidget* theParent )
62   : QLabel( theParent ),
63     myAcceptMoveEvents( false )
64   {
65   }
66   ~ViewLabel() {}
67
68   void setAcceptMoveEvents( bool theFlag )
69   {
70     myAcceptMoveEvents = theFlag;
71   }
72
73 protected:
74   virtual void moveEvent( QMoveEvent* theEvent )
75   {
76     if( myAcceptMoveEvents )
77       QLabel::moveEvent( theEvent );
78     else // return the label to the initial position
79     {
80       myAcceptMoveEvents = true;
81       move( theEvent->oldPos() );
82       myAcceptMoveEvents = false;
83     }
84   }
85
86 private:
87   bool myAcceptMoveEvents;
88 };
89
90 //================================================================
91 // Function : createCursors
92 // Purpose  : 
93 //================================================================
94 void GraphicsView_ViewPort::createCursors ()
95 {
96   defCursor   = new QCursor( Qt::ArrowCursor );
97   handCursor  = new QCursor( Qt::PointingHandCursor );
98   panCursor   = new QCursor( Qt::SizeAllCursor );
99   panglCursor = new QCursor( Qt::CrossCursor );
100
101   SUIT_ResourceMgr* rmgr = SUIT_Session::session()->resourceMgr();
102   zoomCursor   = new QCursor( rmgr->loadPixmap( "GraphicsView", tr( "ICON_GV_CURSOR_ZOOM" ) ) );
103
104   sketchCursor = new QCursor( Qt::CrossCursor );
105 }
106
107 //================================================================
108 // Function : destroyCursors
109 // Purpose  : 
110 //================================================================
111 void GraphicsView_ViewPort::destroyCursors()
112 {
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;
119 }
120
121 //=======================================================================
122 // Name    : GraphicsView_ViewPort
123 // Purpose : Constructor
124 //=======================================================================
125 GraphicsView_ViewPort::GraphicsView_ViewPort( QWidget* theParent )
126 : QGraphicsView( theParent ),
127   myInteractionFlags( 0 ),
128   myViewLabel( 0 ),
129   myViewLabelPosition( VLP_None ),
130   myViewLabelLayout( 0 ),
131   myIsMousePositionEnabled( false ),
132   myForegroundItem( 0 ),
133   myGridItem( 0 ),
134   myIsTransforming( false ),
135   myHighlightedObject( 0 ),
136   myHighlightX( 0 ),
137   myHighlightY( 0 ),
138   myIsHighlighting( false ),
139   mySelectionIterator( 0 ),
140   myRectBand( 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 )
151 {
152   // scene
153   myScene = new GraphicsView_Scene( this );
154   setScene( myScene );
155
156   mySceneGap = 20;
157   myFitAllGap = 40;
158
159   // interaction flags
160   setInteractionFlags( EditFlags );
161   //setInteractionFlag( TraceBoundingRect );
162   //setInteractionFlag( DraggingByMiddleButton );
163   //setInteractionFlag( ImmediateContextMenu );
164   //setInteractionFlag( ImmediateSelection );
165   //setInteractionFlag( Sketching );
166
167   // background
168   setBackgroundBrush( QBrush( Qt::white ) );
169
170   // foreground
171   myIsForegroundEnabled = false;
172   myForegroundSize = QSizeF( 100, 30 );
173   myForegroundMargin = 0.0;
174   myForegroundColor = Qt::white;
175   myForegroundFrameColor = Qt::black;
176   myForegroundFrameLineWidth = 1.0;
177
178   // grid
179   myIsGridEnabled = false;
180   myGridCellSize = 100;
181   myGridLineStyle = Qt::DotLine;
182   myGridLineColor = Qt::darkGray;
183
184   // default index method (BspTreeIndex) leads to
185   // crashes in QGraphicsView::paintEvent() method
186   myScene->setItemIndexMethod( QGraphicsScene::NoIndex );
187
188   // render hints (default - TextAntialiasing only)
189   setRenderHints( QPainter::Antialiasing |
190                   QPainter::TextAntialiasing |
191                   QPainter::SmoothPixmapTransform |
192                   QPainter::HighQualityAntialiasing );
193
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* ) ) );
202
203   connect( myScene, SIGNAL( gsBoundingRectChanged() ),
204            this, SLOT( onBoundingRectChanged() ) );
205
206   initialize();
207 }
208
209 //=======================================================================
210 // Name    : GraphicsView_ViewPort
211 // Purpose : Destructor
212 //=======================================================================
213 GraphicsView_ViewPort::~GraphicsView_ViewPort()
214 {
215   cleanup();
216
217   if( myScene )
218   {
219     delete myScene;
220     myScene = 0;
221   }
222 }
223
224 //================================================================
225 // Function : initialize
226 // Purpose  : 
227 //================================================================
228 void GraphicsView_ViewPort::initialize()
229 {
230   if ( nCounter++ == 0 )
231     createCursors();
232
233   setMouseTracking( true );
234   setFocusPolicy( Qt::StrongFocus );
235 }
236
237 //================================================================
238 // Function : cleanup
239 // Purpose  : 
240 //================================================================
241 void GraphicsView_ViewPort::cleanup()
242 {
243   if ( --nCounter == 0 )
244     destroyCursors();
245 }
246
247 //================================================================
248 // Function : addItem
249 // Purpose  : 
250 //================================================================
251 void GraphicsView_ViewPort::addItem( QGraphicsItem* theItem )
252 {
253   if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( theItem ) )
254   {
255     int aPriority = anObject->getPriority();
256     GraphicsView_ObjectList::iterator anIter, anIterEnd = myObjects.end();
257     for( anIter = myObjects.begin(); anIter != anIterEnd; anIter++ )
258     {
259       if( GraphicsView_Object* anObjectRef = *anIter )
260       {
261         if( anObjectRef->getPriority() > aPriority )
262           break;
263       }
264     }
265     myObjects.insert( anIter, anObject );
266     anObject->setViewTransform( transform() );
267     anObject->addTo( this );
268   }
269   else
270     myScene->addItem( theItem );
271   onBoundingRectChanged();
272 }
273
274 //================================================================
275 // Function : isItemAdded
276 // Purpose  :
277 //================================================================
278 bool GraphicsView_ViewPort::isItemAdded( QGraphicsItem* theItem )
279 {
280   if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( theItem ) )
281   {
282     for( GraphicsView_ObjectList::iterator anIter = myObjects.begin(); anIter != myObjects.end(); anIter++ )
283       if( theItem == *anIter )
284         return true;
285   }
286   else {
287     for( int i = 0; i < myScene->items().size(); i++ )
288       if( theItem == myScene->items().at(i) )
289         return true;
290   }
291   return false;
292 }
293
294 //================================================================
295 // Function : removeItem
296 // Purpose  : 
297 //================================================================
298 void GraphicsView_ViewPort::removeItem( QGraphicsItem* theItem )
299 {
300   if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( theItem ) )
301   {
302     if( myHighlightedObject == anObject )
303       myHighlightedObject = 0;
304     mySelectedObjects.removeAll( anObject );
305     myObjects.removeAll( anObject );
306     anObject->removeFrom( this );
307   }
308   else
309     myScene->removeItem( theItem );
310   onBoundingRectChanged();
311 }
312
313 //================================================================
314 // Function : getObjects
315 // Purpose  : 
316 //================================================================
317 GraphicsView_ObjectList GraphicsView_ViewPort::getObjects( SortType theSortType ) const
318 {
319   if( theSortType == SelectedFirst )
320   {
321     // to append selected objects after their non-selected siblings with similar priority
322     int aCurrentPriority = -1;
323     GraphicsView_ObjectList aSelectedObjects;
324     GraphicsView_ObjectList aTopmostObjects;
325
326     GraphicsView_ObjectList aList;
327     GraphicsView_ObjectListIterator anIter( myObjects );
328     while( anIter.hasNext() )
329     {
330       if( GraphicsView_Object* anObject = anIter.next() )
331       {
332         if( anObject->isOnTop() )
333         {
334           aTopmostObjects.append( anObject );
335           continue;
336         }
337
338         int aPriority = anObject->getPriority();
339         if( aPriority > aCurrentPriority  )
340         {
341           if( !aSelectedObjects.isEmpty() )
342           {
343             aList.append( aSelectedObjects );
344             aSelectedObjects.clear();
345           }
346           aCurrentPriority = aPriority;
347         }
348
349         if( anObject->isSelected() )
350           aSelectedObjects.append( anObject );
351         else
352           aList.append( anObject );
353       }
354     }
355
356     // for selected objects with highest priority,
357     // which were not pushed to the result list yet
358     if( !aSelectedObjects.isEmpty() )
359     {
360       aList.append( aSelectedObjects );
361       aSelectedObjects.clear();
362     }
363
364     aList.append( aTopmostObjects );
365
366     return aList;
367   }
368
369   if( theSortType == SortByZLevel ) // double loop, needs to be optimized
370   {
371     GraphicsView_ObjectList aList;
372
373     GraphicsView_ObjectListIterator anIter( myObjects );
374     while( anIter.hasNext() )
375     {
376       if( GraphicsView_Object* anObject = anIter.next() )
377       {
378         double aZValue = anObject->zValue();
379         GraphicsView_ObjectList::iterator anIter1, anIter1End = aList.end();
380         for( anIter1 = aList.begin(); anIter1 != anIter1End; anIter1++ )
381           if( GraphicsView_Object* anObjectRef = *anIter1 )
382             if( anObjectRef->zValue() > aZValue )
383               break;
384         aList.insert( anIter1, anObject );
385       }
386     }
387     return aList;
388   }
389
390   return myObjects; // theSortType == NoSorting
391 }
392
393 //================================================================
394 // Function : objectsBoundingRect
395 // Purpose  : 
396 //================================================================
397 QRectF GraphicsView_ViewPort::objectsBoundingRect( bool theOnlyVisible ) const
398 {
399   QRectF aRect;
400   QListIterator<QGraphicsItem*> anIter( items() );
401   while( anIter.hasNext() )
402   {
403     if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
404     {
405       if( theOnlyVisible && !anObject->isVisible() )
406         continue;
407
408       QRectF anObjectRect = anObject->getRect();
409       if( !anObjectRect.isNull() )
410       {
411         if( aRect.isNull() )
412           aRect = anObject->getRect();
413         else
414           aRect |= anObject->getRect();
415       }
416     }
417   }
418   return aRect;
419 }
420
421 //================================================================
422 // Function : dumpView
423 // Purpose  : 
424 //================================================================
425 QImage GraphicsView_ViewPort::dumpView( bool theWholeScene,
426                                         QSizeF theSize )
427 {
428   if( !theWholeScene ) // just grab the view contents
429   {
430     QPixmap aPixmap = QPixmap::grabWindow( viewport()->winId() );
431     return aPixmap.toImage();
432   }
433
434   // get a bounding rect of all presented objects
435   // (itemsBoundingRect() method is unsuitable)
436   QRectF aRect = objectsBoundingRect();
437   if( aRect.isNull() )
438     return QImage();
439
440   QRectF aTargetRect( 0, 0, aRect.width(), aRect.height() );
441   if( theSize.isValid() )
442   {
443     double aRatioX = theSize.width() / aTargetRect.width();
444     double aRatioY = theSize.height() / aTargetRect.height();
445     double aRatio = qMin( aRatioX, aRatioY );
446     aTargetRect.setWidth( aTargetRect.width() * aRatio );
447     aTargetRect.setHeight( aTargetRect.height() * aRatio );
448   }
449
450   // render the scene to an image
451   QImage anImage( aTargetRect.toRect().size(), QImage::Format_RGB32 );
452   QPainter aPainter( &anImage );
453   aPainter.setRenderHints( renderHints() );
454
455   myScene->render( &aPainter, aTargetRect, aRect );
456
457   return anImage;
458 }
459
460 //================================================================
461 // Function : setSceneGap
462 // Purpose  : 
463 //================================================================
464 void GraphicsView_ViewPort::setSceneGap( double theSceneGap )
465 {
466   mySceneGap = theSceneGap;
467   onBoundingRectChanged();
468 }
469
470 //================================================================
471 // Function : setFitAllGap
472 // Purpose  : 
473 //================================================================
474 void GraphicsView_ViewPort::setFitAllGap( double theFitAllGap )
475 {
476   myFitAllGap = theFitAllGap;
477 }
478
479 //================================================================
480 // Function : interactionFlags
481 // Purpose  : 
482 //================================================================
483 int GraphicsView_ViewPort::interactionFlags() const
484 {
485   return myInteractionFlags;
486 }
487
488 //================================================================
489 // Function : hasInteractionFlag
490 // Purpose  : 
491 //================================================================
492 bool GraphicsView_ViewPort::hasInteractionFlag( InteractionFlag theFlag )
493 {
494   return ( interactionFlags() & theFlag ) == theFlag;
495 }
496
497 //================================================================
498 // Function : setInteractionFlag
499 // Purpose  : 
500 //================================================================
501 void GraphicsView_ViewPort::setInteractionFlag( InteractionFlag theFlag,
502                                                 bool theIsEnabled )
503 {
504   if( theIsEnabled )
505     setInteractionFlags( myInteractionFlags | theFlag );
506   else
507     setInteractionFlags( myInteractionFlags & ~theFlag );
508 }
509
510 //================================================================
511 // Function : setInteractionFlags
512 // Purpose  : 
513 //================================================================
514 void GraphicsView_ViewPort::setInteractionFlags( InteractionFlags theFlags )
515 {
516   myInteractionFlags = theFlags;
517 }
518
519 //================================================================
520 // Function : setViewLabelPosition
521 // Purpose  : 
522 //================================================================
523 void GraphicsView_ViewPort::setViewLabelPosition( ViewLabelPosition thePosition,
524                                                   bool theIsForced )
525 {
526   if( theIsForced && !myViewLabel )
527     myViewLabel = new ViewLabel( viewport() );
528
529   if( !myViewLabel )
530     return;
531
532   if( thePosition == VLP_None )
533   {
534     myViewLabel->setVisible( false );
535     return;
536   }
537
538   if( myViewLabelLayout )
539     delete myViewLabelLayout;
540
541   myViewLabelLayout = new QGridLayout( viewport() );
542   myViewLabelLayout->setMargin( 10 );
543   myViewLabelLayout->setSpacing( 0 );
544
545   int aRow = 0, aColumn = 0;
546   switch( thePosition )
547   {
548     case VLP_TopLeft:     aRow = 0; aColumn = 0; break;
549     case VLP_TopRight:    aRow = 0; aColumn = 1; break;
550     case VLP_BottomLeft:  aRow = 1; aColumn = 0; break;
551     case VLP_BottomRight: aRow = 1; aColumn = 1; break;
552     default: break;
553   }
554
555   myViewLabelLayout->addWidget( myViewLabel, aRow, aColumn );
556   myViewLabelLayout->setRowStretch( 1 - aRow, 1 );
557   myViewLabelLayout->setColumnStretch( 1 - aColumn, 1 );
558
559   myViewLabel->setVisible( true );
560 }
561
562 //================================================================
563 // Function : setViewLabelText
564 // Purpose  : 
565 //================================================================
566 void GraphicsView_ViewPort::setViewLabelText( const QString& theText )
567 {
568   if( myViewLabel )
569     myViewLabel->setText( theText );
570 }
571
572 //================================================================
573 // Function : setMousePositionEnabled
574 // Purpose  : 
575 //================================================================
576 void GraphicsView_ViewPort::setMousePositionEnabled( bool theState )
577 {
578   myIsMousePositionEnabled = theState;
579
580   if( theState )
581   {
582     setViewLabelPosition( VLP_BottomLeft, true );
583
584     int aMouseX = 0, aMouseY = 0;
585     setViewLabelText( QString( "(%1, %2)" ).arg( aMouseX ).arg( aMouseY ) );
586   }
587   else
588     setViewLabelPosition( VLP_None );
589 }
590
591 //================================================================
592 // Function : backgroundColor
593 // Purpose  : 
594 //================================================================
595 QColor GraphicsView_ViewPort::backgroundColor() const
596 {
597   return backgroundBrush().color();
598 }
599
600 //================================================================
601 // Function : setBackgroundColor
602 // Purpose  : 
603 //================================================================
604 void GraphicsView_ViewPort::setBackgroundColor( const QColor& theColor )
605 {
606   setBackgroundBrush( QBrush( theColor ) );
607 }
608
609 //================================================================
610 // Function : setForegroundEnabled
611 // Purpose  : 
612 //================================================================
613 void GraphicsView_ViewPort::setForegroundEnabled( bool theState )
614 {
615   myIsForegroundEnabled = theState;
616 }
617
618 //================================================================
619 // Function : setForegroundSize
620 // Purpose  : 
621 //================================================================
622 void GraphicsView_ViewPort::setForegroundSize( const QSizeF& theSize )
623 {
624   myForegroundSize = theSize;
625 }
626
627 //================================================================
628 // Function : setForegroundMargin
629 // Purpose  : 
630 //================================================================
631 void GraphicsView_ViewPort::setForegroundMargin( double theMargin )
632 {
633   myForegroundMargin = theMargin;
634 }
635
636 //================================================================
637 // Function : setForegroundColor
638 // Purpose  : 
639 //================================================================
640 void GraphicsView_ViewPort::setForegroundColor( const QColor& theColor )
641 {
642   myForegroundColor = theColor;
643 }
644
645 //================================================================
646 // Function : setForegroundFrameColor
647 // Purpose  : 
648 //================================================================
649 void GraphicsView_ViewPort::setForegroundFrameColor( const QColor& theColor )
650 {
651   myForegroundFrameColor = theColor;
652 }
653
654 //================================================================
655 // Function : setForegroundFrameLineWidth
656 // Purpose  : 
657 //================================================================
658 void GraphicsView_ViewPort::setForegroundFrameLineWidth( double theLineWidth )
659 {
660   myForegroundFrameLineWidth = theLineWidth;
661 }
662
663 //================================================================
664 // Function : updateForeground
665 // Purpose  : 
666 //================================================================
667 void GraphicsView_ViewPort::updateForeground()
668 {
669   if( myIsForegroundEnabled )
670   {
671     if( !myForegroundItem )
672       myForegroundItem = myScene->addRect( QRectF(), QPen(), QBrush( Qt::white ) );
673     myForegroundItem->setZValue( FOREGROUND_Z_VALUE );
674
675     QPointF aPoint = QPointF();
676     QRectF aRect( aPoint, myForegroundSize );
677     aRect.adjust( -myForegroundMargin, -myForegroundMargin,
678                   myForegroundMargin, myForegroundMargin );
679     myForegroundItem->setRect( aRect );
680
681     QBrush aBrush = myForegroundItem->brush();
682     aBrush.setColor( myForegroundColor );
683     myForegroundItem->setBrush( aBrush );
684
685     QPen aPen = myForegroundItem->pen();
686     aPen.setColor( myForegroundFrameColor );
687     aPen.setWidthF( myForegroundFrameLineWidth );
688     myForegroundItem->setPen( aPen );
689
690     myForegroundItem->setVisible( true );
691
692     myScene->setSceneRect( aRect.adjusted( -mySceneGap, -mySceneGap, mySceneGap, mySceneGap ) );
693   }
694   else
695   {
696     if( myForegroundItem )
697       myForegroundItem->setVisible( false );
698   }
699
700   updateGrid(); // foreground size could be changed
701 }
702
703 //================================================================
704 // Function : setGridEnabled
705 // Purpose  : 
706 //================================================================
707 void GraphicsView_ViewPort::setGridEnabled( bool theState )
708 {
709   myIsGridEnabled = theState;
710 }
711
712 //================================================================
713 // Function : setGridCellSize
714 // Purpose  : 
715 //================================================================
716 void GraphicsView_ViewPort::setGridCellSize( int theCellSize )
717 {
718   myGridCellSize = theCellSize;
719 }
720
721 //================================================================
722 // Function : setGridLineStyle
723 // Purpose  : 
724 //================================================================
725 void GraphicsView_ViewPort::setGridLineStyle( int theLineStyle )
726 {
727   myGridLineStyle = theLineStyle;
728 }
729
730 //================================================================
731 // Function : setGridLineColor
732 // Purpose  : 
733 //================================================================
734 void GraphicsView_ViewPort::setGridLineColor( const QColor& theLineColor )
735 {
736   myGridLineColor = theLineColor;
737 }
738
739 //================================================================
740 // Function : updateGrid
741 // Purpose  : 
742 //================================================================
743 void GraphicsView_ViewPort::updateGrid()
744 {
745   if( myIsGridEnabled )
746   {
747     if( !myGridItem )
748       myGridItem = myScene->addPath( QPainterPath() );
749     myGridItem->setZValue( GRID_Z_VALUE );
750
751     double aWidth = myForegroundSize.width();
752     double aHeight = myForegroundSize.height();
753
754     int aGridNbX = int( aWidth / myGridCellSize ) + 1;
755     int aGridNbY = int( aHeight / myGridCellSize ) + 1;
756
757     int anIndex;
758     QPainterPath aPath;
759     for( anIndex = 0; anIndex < aGridNbX; anIndex++ )
760     {
761       double x = myGridCellSize * (double)anIndex;
762       aPath.moveTo( x, 0 );
763       aPath.lineTo( x, aHeight );
764     }
765     for( anIndex = 0; anIndex < aGridNbY; anIndex++ )
766     {
767       double y = myGridCellSize * (double)anIndex;
768       aPath.moveTo( 0, y );
769       aPath.lineTo( aWidth, y );
770     }
771     myGridItem->setPath( aPath );
772
773     QPen aPen = myGridItem->pen();
774     aPen.setStyle( (Qt::PenStyle)myGridLineStyle );
775     aPen.setColor( myGridLineColor );
776     myGridItem->setPen( aPen );
777
778     myGridItem->setVisible( true );
779   }
780   else
781   {
782     if( myGridItem )
783       myGridItem->setVisible( false );
784   }
785 }
786
787 //================================================================
788 // Function : reset
789 // Purpose  : 
790 //================================================================
791 void GraphicsView_ViewPort::reset()
792 {
793   fitAll();
794 }
795
796 //================================================================
797 // Function : pan
798 // Purpose  : 
799 //================================================================
800 void GraphicsView_ViewPort::pan( double theDX, double theDY )
801 {
802   myIsTransforming = true;
803
804   if( myViewLabel )
805     myViewLabel->setAcceptMoveEvents( false );
806
807   if( QScrollBar* aHBar = horizontalScrollBar() )
808     aHBar->setValue( aHBar->value() - theDX );
809   if( QScrollBar* aVBar = verticalScrollBar() )
810     aVBar->setValue( aVBar->value() + theDY );
811
812   if( myViewLabel )
813     myViewLabel->setAcceptMoveEvents( true );
814
815   myIsTransforming = false;
816
817   applyTransform();
818 }
819
820 //================================================================
821 // Function : setCenter
822 // Purpose  : 
823 //================================================================
824 void GraphicsView_ViewPort::setCenter( double theX, double theY )
825 {
826   myIsTransforming = true;
827
828   setTransform( myCurrentTransform );
829   centerOn( theX, theY );
830
831   myIsTransforming = false;
832
833   applyTransform();
834 }
835
836 //================================================================
837 // Function : zoom
838 // Purpose  : 
839 //================================================================
840 void GraphicsView_ViewPort::zoom( double theX1, double theY1, double theX2, double theY2 )
841 {
842   myIsTransforming = true;
843
844   double aDX = theX2 - theX1;
845   double aDY = theY2 - theY1;
846   double aZoom = sqrt( aDX * aDX + aDY * aDY ) / 100 + 1;
847   aZoom = ( aDX > 0 ) ?  aZoom : 1 / aZoom;
848
849   QTransform aTransform = transform();
850   aTransform.scale( aZoom, aZoom );
851   double aM11 = aTransform.m11();
852   double aM22 = aTransform.m22();
853
854
855   QGraphicsView::ViewportAnchor old_anchor = transformationAnchor();
856   setTransformationAnchor( QGraphicsView::AnchorUnderMouse );
857
858   // increasing of diagonal coefficients (>300) leads to a crash sometimes
859   // at the values of 100 some primitives are drawn incorrectly
860   if( qMax( aM11, aM22 ) < 100 )
861     setTransform( aTransform );
862
863   myIsTransforming = false;
864
865   applyTransform();
866
867   setTransformationAnchor( old_anchor );
868 }
869
870 //================================================================
871 // Function : fitRect
872 // Purpose  : 
873 //================================================================
874 void GraphicsView_ViewPort::fitRect( const QRectF& theRect )
875 {
876   myIsTransforming = true;
877
878   fitInView( theRect, Qt::KeepAspectRatio );
879
880   myIsTransforming = false;
881
882   applyTransform();
883 }
884
885 //================================================================
886 // Function : fitSelect
887 // Purpose  : 
888 //================================================================
889 void GraphicsView_ViewPort::fitSelect()
890 {
891   myIsTransforming = true;
892
893   QRectF aGlobalRect;
894   for( initSelected(); moreSelected(); nextSelected() )
895   {
896     if( GraphicsView_Object* aMovingObject = selectedObject() )
897     {
898       QRectF aRect = aMovingObject->getRect();
899       if( aGlobalRect.isNull() )
900         aGlobalRect = aRect;
901       else
902         aGlobalRect |= aRect;
903     }
904   }
905
906   if( !aGlobalRect.isNull() )
907   {
908     double aGap = qMax( aGlobalRect.width(), aGlobalRect.height() ) / 5;
909     aGlobalRect.adjust( -aGap, -aGap, aGap, aGap );
910     fitInView( aGlobalRect, Qt::KeepAspectRatio );
911   }
912
913   myIsTransforming = false;
914
915   applyTransform();
916 }
917
918 //================================================================
919 // Function : fitAll
920 // Purpose  : 
921 //================================================================
922 void GraphicsView_ViewPort::fitAll( bool theKeepScale )
923 {
924   myIsTransforming = true;
925
926   if( theKeepScale )
927     myCurrentTransform = transform();
928
929   double aGap = myFitAllGap;
930   QRectF aRect = objectsBoundingRect( true );
931   fitInView( aRect.adjusted( -aGap, -aGap, aGap, aGap ), Qt::KeepAspectRatio );
932
933   myIsTransforming = false;
934
935   applyTransform();
936 }
937
938 //================================================================
939 // Function : fitWidth
940 // Purpose  : 
941 //================================================================
942 void GraphicsView_ViewPort::fitWidth()
943 {
944   myIsTransforming = true;
945
946   double aGap = myFitAllGap;
947   QRectF aRect = objectsBoundingRect( true );
948
949   double aTop = aRect.top();
950   double aLeft = aRect.left();
951   double aMargin = 10;
952
953   aRect.setY( aRect.center().y() );
954   aRect.setHeight( aMargin );
955
956   fitInView( aRect.adjusted( -aGap, -aGap, aGap, aGap ), Qt::KeepAspectRatio );
957   ensureVisible( aLeft, aTop, aMargin, aMargin, 0, aGap );
958
959   myIsTransforming = false;
960
961   applyTransform();
962 }
963
964 //================================================================
965 // Function : applyTransform
966 // Purpose  : 
967 //================================================================
968 void GraphicsView_ViewPort::applyTransform()
969 {
970   GraphicsView_ObjectListIterator anIter( getObjects() );
971   while( anIter.hasNext() )
972     if( GraphicsView_Object* anObject = anIter.next() )
973       anObject->setViewTransform( transform() );
974 }
975
976 //================================================================
977 // Function : currentBlock
978 // Purpose  : 
979 //================================================================
980 GraphicsView_ViewPort::BlockStatus GraphicsView_ViewPort::currentBlock()
981 {
982   if( isDragging() && !myDragPosition.isNull() )
983     return BlockStatus( BS_Selection );
984
985   if( myAreSelectionPointsInitialized && ( myFirstSelectionPoint != myLastSelectionPoint ) )
986     return BlockStatus( BS_Selection );
987
988   if( isPulling() )
989     return BlockStatus( BS_Selection );
990
991   return BS_NoBlock;
992 }
993
994 //================================================================
995 // Function : highlight
996 // Purpose  : 
997 //================================================================
998 void GraphicsView_ViewPort::highlight( double theX, double theY )
999 {
1000   myIsHighlighting = true;
1001   myHighlightX = theX;
1002   myHighlightY = theY;
1003
1004   bool anIsHighlighted = false;
1005   bool anIsOnObject = false;
1006
1007   GraphicsView_Object* aPreviousHighlightedObject = myHighlightedObject;
1008   GraphicsView_Object* aHighlightedObject = 0;
1009
1010   QCursor aCursor;
1011
1012   GraphicsView_ObjectList aList = getObjects( SortByZLevel );
1013   GraphicsView_ObjectListIterator anIter( aList );
1014   anIter.toBack(); // objects with higher priority have to be checked earlier
1015   while( anIter.hasPrevious() )
1016   {
1017     if( GraphicsView_Object* anObject = anIter.previous() )
1018     {
1019       if( anObject->isVisible() && anObject->isSelectable() )
1020       {
1021         if( anObject->checkHighlight( theX, theY, aCursor ) )
1022         {
1023           anIsOnObject = true;
1024           anIsHighlighted = anObject->highlight( theX, theY );
1025         }
1026
1027         if( anIsHighlighted )
1028         {
1029           aHighlightedObject = anObject;
1030           break;
1031         }
1032       }
1033     }
1034   }
1035
1036   setCursor( aCursor );
1037
1038   if( !anIsOnObject )
1039   {
1040     anIter = aList;
1041     while( anIter.hasNext() )
1042       if( GraphicsView_Object* anObject = anIter.next() )
1043         anObject->unhighlight();
1044
1045     myHighlightedObject = 0;
1046     return;
1047   }
1048   else if( !myHighlightedObject && anIsHighlighted )
1049   {
1050     myHighlightedObject = aHighlightedObject;
1051   }
1052   else if( myHighlightedObject && !anIsHighlighted )
1053   {
1054     myHighlightedObject->unhighlight();
1055     myHighlightedObject = 0;
1056   }
1057   else if( myHighlightedObject && anIsHighlighted )
1058   {
1059     myHighlightedObject->highlight( theX, theY );
1060     if( myHighlightedObject != aHighlightedObject )
1061     {
1062       myHighlightedObject->unhighlight();
1063       myHighlightedObject = aHighlightedObject;
1064     }
1065   }
1066 }
1067
1068 //================================================================
1069 // Function : clearHighlighted
1070 // Purpose  : 
1071 //================================================================
1072 void GraphicsView_ViewPort::clearHighlighted()
1073 {
1074   if( myHighlightedObject )
1075   {
1076     myHighlightedObject->unhighlight();
1077     myHighlightedObject = 0;
1078   }
1079 }
1080
1081 //================================================================
1082 // Function : select
1083 // Purpose  : 
1084 //================================================================
1085 int GraphicsView_ViewPort::select( const QRectF& theRect, bool theIsAppend )
1086 {
1087   if( !myIsHighlighting )
1088     return GVSS_NoChanged;
1089
1090   GV_SelectionStatus aStatus = GVSS_Invalid;
1091   if( theRect.isNull() ) // point selection
1092   {
1093     if( myHighlightedObject )
1094     {
1095       if( mySelectedObjects.count() == 1 &&
1096           mySelectedObjects.first() == myHighlightedObject )
1097         aStatus = GVSS_LocalChanged;
1098
1099       if( !theIsAppend )
1100       {
1101         GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1102         while( anIter.hasNext() )
1103           if( GraphicsView_Object* anObject = anIter.next() )
1104             if( myHighlightedObject != anObject )
1105               anObject->unselect();
1106
1107         if( !mySelectedObjects.isEmpty() && aStatus == GVSS_Invalid )
1108           aStatus = GVSS_GlobalChanged;
1109         mySelectedObjects.clear();
1110       } 
1111       else if( myHighlightedObject->isSelected() && aStatus != GVSS_LocalChanged )
1112       {
1113         mySelectedObjects.removeAll( myHighlightedObject );
1114         myHighlightedObject->unselect();
1115
1116         if( !mySelectedObjects.isEmpty() && aStatus == GVSS_Invalid )
1117           aStatus = GVSS_GlobalChanged;
1118
1119         return aStatus;
1120       }
1121
1122       if( myHighlightedObject->select( myHighlightX, myHighlightY, QRectF() ) &&
1123           mySelectedObjects.indexOf( myHighlightedObject ) == -1 )
1124       {
1125         mySelectedObjects.append( myHighlightedObject );
1126         if( aStatus == GVSS_Invalid )
1127           aStatus = GVSS_GlobalChanged;
1128       }
1129       else if( aStatus == GVSS_LocalChanged )
1130         aStatus = GVSS_GlobalChanged;
1131
1132       return aStatus;
1133     }
1134
1135     if( !myHighlightedObject )
1136     {
1137       if( !theIsAppend )
1138       {
1139         GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1140         while( anIter.hasNext() )
1141           if( GraphicsView_Object* anObject = anIter.next() )
1142             if( myHighlightedObject != anObject )
1143               anObject->unselect();
1144
1145         if( !mySelectedObjects.isEmpty() )
1146           aStatus = GVSS_GlobalChanged;
1147         mySelectedObjects.clear();
1148       }
1149       return aStatus;
1150     }
1151
1152     return GVSS_NoChanged;
1153   }
1154   else // rectangle selection
1155   {
1156     aStatus = GVSS_NoChanged;
1157
1158     bool updateAll = false;
1159     if( !theIsAppend )
1160     {
1161       if( !mySelectedObjects.isEmpty() )
1162         aStatus = GVSS_GlobalChanged;
1163
1164       GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1165       while( anIter.hasNext() )
1166         if( GraphicsView_Object* anObject = anIter.next() )
1167           if( myHighlightedObject != anObject )
1168             anObject->unselect();
1169       mySelectedObjects.clear();
1170     }
1171
1172     QListIterator<QGraphicsItem*> anIter( items() );
1173     while( anIter.hasNext() )
1174     {
1175       if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1176       {
1177         if( anObject->isVisible() && anObject->isSelectable() )
1178         {
1179           bool anIsSelected = false;
1180           QRectF aRect = anObject->getRect();
1181           if( theRect.contains( aRect ) && myIsHighlighting )
1182             anIsSelected = anObject->select( myHighlightX, myHighlightY, theRect );
1183
1184           if( anIsSelected && mySelectedObjects.indexOf( anObject ) == -1 )
1185           {
1186             mySelectedObjects.append( anObject );
1187             aStatus = GVSS_GlobalChanged;
1188           }
1189         }
1190       }
1191     }
1192   }
1193   return aStatus;
1194 }
1195
1196 //================================================================
1197 // Function : clearSelected
1198 // Purpose  : 
1199 //================================================================
1200 void GraphicsView_ViewPort::clearSelected()
1201 {
1202   GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1203   while( anIter.hasNext() )
1204     if( GraphicsView_Object* anObject = anIter.next() )
1205       anObject->unselect();
1206   mySelectedObjects.clear();
1207 }
1208
1209 //================================================================
1210 // Function : setSelected
1211 // Purpose  : 
1212 //================================================================
1213 void GraphicsView_ViewPort::setSelected( GraphicsView_Object* theObject )
1214 {
1215   if( theObject )
1216   {
1217     theObject->setSelected( true );
1218     mySelectedObjects.append( theObject );
1219   }
1220 }
1221
1222 //================================================================
1223 // Function : nbSelected
1224 // Purpose  : 
1225 //================================================================
1226 int GraphicsView_ViewPort::nbSelected() const
1227 {
1228   return mySelectedObjects.count();
1229 }
1230
1231 //================================================================
1232 // Function : initSelected
1233 // Purpose  : 
1234 //================================================================
1235 void GraphicsView_ViewPort::initSelected()
1236 {
1237   mySelectionIterator = 0;
1238 }
1239
1240 //================================================================
1241 // Function : moreSelected
1242 // Purpose  : 
1243 //================================================================
1244 bool GraphicsView_ViewPort::moreSelected()
1245 {
1246   return mySelectionIterator < nbSelected();
1247 }
1248
1249 //================================================================
1250 // Function : nextSelected
1251 // Purpose  : 
1252 //================================================================
1253 bool GraphicsView_ViewPort::nextSelected()
1254 {
1255   if( mySelectionIterator >= 0 && mySelectionIterator < nbSelected() )
1256   {
1257     mySelectionIterator++;
1258     return true;
1259   }
1260   return false;
1261 }
1262
1263 //================================================================
1264 // Function : selectedObject
1265 // Purpose  : 
1266 //================================================================
1267 GraphicsView_Object* GraphicsView_ViewPort::selectedObject()
1268 {
1269   if( mySelectionIterator >= 0 && mySelectionIterator < nbSelected() )
1270     return mySelectedObjects[ mySelectionIterator ];
1271   return 0;
1272 }
1273
1274 //================================================================
1275 // Function : startSelectByRect
1276 // Purpose  : 
1277 //================================================================
1278 void GraphicsView_ViewPort::startSelectByRect( int x, int y )
1279 {
1280   if( !myAreSelectionPointsInitialized )
1281   {
1282     myFirstSelectionPoint = QPoint( x, y );
1283     myLastSelectionPoint = QPoint( x, y );
1284     myAreSelectionPointsInitialized = true;
1285   }
1286
1287   if( !myRectBand )
1288   {
1289     myRectBand = new QRubberBand( QRubberBand::Rectangle, this );
1290     QPalette palette;
1291     palette.setColor( myRectBand->foregroundRole(), Qt::white );
1292     myRectBand->setPalette( palette );
1293   }
1294   myRectBand->hide();
1295 }
1296
1297 //================================================================
1298 // Function : drawSelectByRect
1299 // Purpose  : 
1300 //================================================================
1301 void GraphicsView_ViewPort::drawSelectByRect( int x, int y )
1302 {
1303   if( myAreSelectionPointsInitialized )
1304   {
1305     myRectBand->hide();
1306
1307     myLastSelectionPoint.setX( x );
1308     myLastSelectionPoint.setY( y );
1309
1310     QRect aRect = selectionRect();
1311     myRectBand->setGeometry( aRect );
1312     myRectBand->setVisible( aRect.isValid() );
1313   }
1314 }
1315
1316 //================================================================
1317 // Function : isSelectByRect
1318 // Purpose  : 
1319 //================================================================
1320 bool GraphicsView_ViewPort::isSelectByRect() const
1321 {
1322   return myAreSelectionPointsInitialized;
1323 }
1324
1325 //================================================================
1326 // Function : finishSelectByRect
1327 // Purpose  : 
1328 //================================================================
1329 void GraphicsView_ViewPort::finishSelectByRect()
1330 {
1331   if( myAreSelectionPointsInitialized )
1332   {
1333     if( myRectBand )
1334     {
1335       myRectBand->hide();
1336       delete myRectBand;
1337       myRectBand = 0;
1338     }
1339
1340     myAreSelectionPointsInitialized = false;
1341   }
1342 }
1343
1344 //================================================================
1345 // Function : selectionRect
1346 // Purpose  : 
1347 //================================================================
1348 QRect GraphicsView_ViewPort::selectionRect()
1349 {
1350   QRect aRect;
1351   if( myAreSelectionPointsInitialized )
1352   {
1353     aRect.setLeft( qMin( myFirstSelectionPoint.x(), myLastSelectionPoint.x() ) );
1354     aRect.setTop( qMin( myFirstSelectionPoint.y(), myLastSelectionPoint.y() ) );
1355     aRect.setRight( qMax( myFirstSelectionPoint.x(), myLastSelectionPoint.x() ) );
1356     aRect.setBottom( qMax( myFirstSelectionPoint.y(), myLastSelectionPoint.y() ) );
1357   }
1358   return aRect;
1359 }
1360
1361 //================================================================
1362 // Function : prepareToSketch
1363 // Purpose  : 
1364 //================================================================
1365 void GraphicsView_ViewPort::prepareToSketch( bool theStatus )
1366 {
1367   myIsPrepareToSketch = theStatus;
1368   if( theStatus )
1369     setCursor( *getSketchCursor() );
1370 }
1371
1372 //================================================================
1373 // Function : isPrepareToSketch
1374 // Purpose  : 
1375 //================================================================
1376 bool GraphicsView_ViewPort::isPrepareToSketch()
1377 {
1378   return myIsPrepareToSketch;
1379 }
1380
1381 //================================================================
1382 // Function : startSketching
1383 // Purpose  : 
1384 //================================================================
1385 void GraphicsView_ViewPort::startSketching( const QPointF& thePoint,
1386                                             bool theIsPath )
1387 {
1388   prepareToSketch( false );
1389
1390   if( !mySketchingItem )
1391   {
1392     mySketchingItem = new QGraphicsPathItem();
1393     mySketchingItem->setZValue( SKETCH_Z_VALUE );
1394
1395     QPen aPen = mySketchingItem->pen();
1396     aPen.setStyle( Qt::DotLine );
1397     mySketchingItem->setPen( aPen );
1398
1399     addItem( mySketchingItem );
1400   }
1401
1402   mySketchingPoint = thePoint;
1403
1404   QPainterPath aPath;
1405   aPath.moveTo( mySketchingPoint );
1406   mySketchingItem->setPath( aPath );
1407   mySketchingItem->setVisible( true );
1408
1409   myIsSketching = true;
1410   myIsSketchingByPath = theIsPath;
1411 }
1412
1413 //================================================================
1414 // Function : drawSketching
1415 // Purpose  : 
1416 //================================================================
1417 void GraphicsView_ViewPort::drawSketching( const QPointF& thePoint )
1418 {
1419   bool anIsPath = false;
1420   if( mySketchingItem && isSketching( &anIsPath ) )
1421   {
1422     QPainterPath aPath = mySketchingItem->path();
1423     if( anIsPath ) // arbitrary path
1424       aPath.lineTo( thePoint );
1425     else // rectangle
1426     {
1427       // make a valid rectangle
1428       double x1 = mySketchingPoint.x(), y1 = mySketchingPoint.y();
1429       double x2 = thePoint.x(), y2 = thePoint.y();
1430       QPointF aPoint1( qMin( x1, x2 ), qMin( y1, y2 ) );
1431       QPointF aPoint2( qMax( x1, x2 ), qMax( y1, y2 ) );
1432       QRectF aRect( aPoint1, aPoint2 );
1433
1434       aPath = QPainterPath();
1435       aPath.addRect( aRect );
1436     }
1437     mySketchingItem->setPath( aPath );
1438   }
1439 }
1440
1441 //================================================================
1442 // Function : finishSketching
1443 // Purpose  : 
1444 //================================================================
1445 void GraphicsView_ViewPort::finishSketching( bool theStatus )
1446 {
1447   prepareToSketch( false );
1448
1449   mySketchingItem->setVisible( false );
1450   myIsSketching = false;
1451
1452   setCursor( *getDefaultCursor() );
1453
1454   if( theStatus )
1455   {
1456     QPainterPath aPath = mySketchingItem->path();
1457     emit vpSketchingFinished( aPath );
1458   }
1459 }
1460
1461 //================================================================
1462 // Function : isSketching
1463 // Purpose  : 
1464 //================================================================
1465 bool GraphicsView_ViewPort::isSketching( bool* theIsPath ) const
1466 {
1467   if( theIsPath )
1468     *theIsPath = myIsSketchingByPath;
1469   return myIsSketching;
1470 }
1471
1472 //================================================================
1473 // Function : dragObjects
1474 // Purpose  : 
1475 //================================================================
1476 void GraphicsView_ViewPort::dragObjects( QGraphicsSceneMouseEvent* e )
1477 {
1478   GraphicsView_Object* anObject = getHighlightedObject();
1479
1480   if( myDragPosition.isNull() )
1481   {
1482     myDragPosition = e->scenePos();
1483     return;
1484   }
1485
1486   GraphicsView_ObjectList anObjectsToMove;
1487   if( anObject && anObject->isMovable() && ( e->buttons() & Qt::LeftButton ) )
1488   {
1489     if( anObject->isSelected() )
1490     {
1491       for( initSelected(); moreSelected(); nextSelected() )
1492         if( GraphicsView_Object* aMovingObject = selectedObject() )
1493           if( aMovingObject->isMovable() )
1494             anObjectsToMove.append( aMovingObject );
1495     }
1496     else
1497       anObjectsToMove.append( anObject );
1498   }
1499   else if( hasInteractionFlag( DraggingByMiddleButton ) &&
1500            nbSelected() && ( e->buttons() & Qt::MidButton ) )
1501   {
1502     for( initSelected(); moreSelected(); nextSelected() )
1503       if( GraphicsView_Object* aMovingObject = selectedObject() )
1504         if( aMovingObject->isMovable() )
1505           anObjectsToMove.append( aMovingObject );
1506   }
1507
1508   if( anObjectsToMove.isEmpty() )
1509     return;
1510
1511   double aDX = e->scenePos().x() - myDragPosition.x();
1512   double aDY = e->scenePos().y() - myDragPosition.y();
1513
1514   bool anIsMovingByXAllowed = true, anIsMovingByYAllowed = true;
1515   GraphicsView_ObjectListIterator anIter( anObjectsToMove );
1516   while( anIter.hasNext() )
1517     if( GraphicsView_Object* aMovingObject = anIter.next() )
1518     {
1519       if( !aMovingObject->isMovingByXAllowed( aDX ) )
1520         anIsMovingByXAllowed = false;
1521       if( !aMovingObject->isMovingByYAllowed( aDY ) )
1522         anIsMovingByYAllowed = false;
1523     }
1524
1525   if( !anIsMovingByXAllowed && !anIsMovingByYAllowed )
1526     return; // myDragPosition shouldn't be changed
1527
1528   if( !anIsMovingByXAllowed )
1529     aDX = 0;
1530
1531   if( !anIsMovingByYAllowed )
1532     aDY = 0;
1533
1534   anIter = anObjectsToMove;
1535   while( anIter.hasNext() )
1536     if( GraphicsView_Object* aMovingObject = anIter.next() )
1537       aMovingObject->move( aDX, aDY );
1538
1539   if( anIsMovingByXAllowed )
1540     myDragPosition.setX( e->scenePos().x() );
1541
1542   if( anIsMovingByYAllowed )
1543     myDragPosition.setY( e->scenePos().y() );
1544 }
1545
1546 //================================================================
1547 // Function : startPulling
1548 // Purpose  : 
1549 //================================================================
1550 bool GraphicsView_ViewPort::startPulling( const QPointF& thePoint )
1551 {
1552   QListIterator<QGraphicsItem*> anIter( items() );
1553   while( anIter.hasNext() )
1554   {
1555     if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1556     {
1557       QRectF aRect = anObject->getPullingRect();
1558       if( aRect.contains( thePoint ) && anObject->startPulling( thePoint ) )
1559       {
1560         myIsPulling = true;
1561         myPullingObject = anObject;
1562         //setCursor( *getHandCursor() ); // testing ImageViewer
1563         return true;
1564       }
1565     }
1566   }
1567   return false;
1568 }
1569
1570 //================================================================
1571 // Function : drawPulling
1572 // Purpose  : 
1573 //================================================================
1574 void GraphicsView_ViewPort::drawPulling( const QPointF& thePoint )
1575 {
1576   GraphicsView_Object* aLockedObject = 0;
1577
1578   QListIterator<QGraphicsItem*> anIter( items() );
1579   while( anIter.hasNext() )
1580   {
1581     if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1582     {
1583       if( !anObject->isVisible() )
1584         continue;
1585
1586       QRectF aRect = anObject->getPullingRect();
1587       if( aRect.contains( thePoint ) && anObject->portContains( thePoint ) )
1588       {
1589         aLockedObject = anObject;
1590         break;
1591       }
1592     }
1593   }
1594
1595   myPullingObject->pull( thePoint, aLockedObject, getSelectedObjects() );
1596 }
1597
1598 //================================================================
1599 // Function : finishPulling
1600 // Purpose  : 
1601 //================================================================
1602 void GraphicsView_ViewPort::finishPulling( bool theStatus )
1603 {
1604   myIsPulling = false;
1605   myPullingObject->finishPulling( theStatus, getSelectedObjects() );
1606   setCursor( *getDefaultCursor() );
1607 }
1608
1609 //================================================================
1610 // Function : cancelCurrentOperation
1611 // Purpose  : 
1612 //================================================================
1613 bool GraphicsView_ViewPort::cancelCurrentOperation()
1614 {
1615   myIsHighlighting = false;
1616
1617   if( isDragging() )
1618   {
1619     for( initSelected(); moreSelected(); nextSelected() )
1620       if( GraphicsView_Object* aMovingObject = selectedObject() )
1621         aMovingObject->finishMove( false );
1622
1623     if( GraphicsView_Object* aMovingObject = getHighlightedObject() )
1624       aMovingObject->finishMove( false );
1625
1626     myIsDragging = false;
1627     myDragPosition = QPointF();
1628     //setCursor( myStoredCursor );
1629     setCursor( *getDefaultCursor() );
1630
1631     return true;
1632   }
1633
1634   if( isPulling() )
1635   {
1636     finishPulling( false );
1637     return true;
1638   }
1639
1640   if( isSketching() || isPrepareToSketch() )
1641   {
1642     finishSketching( false );
1643     return true;
1644   }
1645
1646   return false;
1647 }
1648
1649 //================================================================
1650 // Function : onBoundingRectChanged
1651 // Purpose  : 
1652 //================================================================
1653 void GraphicsView_ViewPort::onBoundingRectChanged()
1654 {
1655   if( hasInteractionFlag( TraceBoundingRect ) )
1656   {
1657     QRectF aRect = objectsBoundingRect( true );
1658     myScene->setSceneRect( aRect.adjusted( -mySceneGap, -mySceneGap, mySceneGap, mySceneGap ) );
1659   }
1660 }
1661
1662 //================================================================
1663 // Function : onKeyEvent
1664 // Purpose  : 
1665 //================================================================
1666 void GraphicsView_ViewPort::onKeyEvent( QKeyEvent* e )
1667 {
1668   emit vpKeyEvent( e );
1669 }
1670
1671 //================================================================
1672 // Function : onMouseEvent
1673 // Purpose  : 
1674 //================================================================
1675 void GraphicsView_ViewPort::onMouseEvent( QGraphicsSceneMouseEvent* e )
1676 {
1677   emit vpMouseEvent( e );
1678
1679   bool anIsHandled = false;
1680   switch( e->type() )
1681   {
1682     case QEvent::GraphicsSceneMousePress:
1683     {
1684       if( hasInteractionFlag( EditFlags ) && nbSelected() )
1685         for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1686           if( GraphicsView_Object* anObject = selectedObject() )
1687             anIsHandled = anObject->handleMousePress( e );
1688
1689       if( !anIsHandled && hasInteractionFlag( Dragging ) )
1690       {
1691         bool anAccel = e->modifiers() & GraphicsView_ViewTransformer::accelKey();
1692         if( ( getHighlightedObject() &&
1693               getHighlightedObject()->isMovable() &&
1694               !( anAccel || e->button() != Qt::LeftButton ) ) ||
1695             ( hasInteractionFlag( DraggingByMiddleButton ) &&
1696               nbSelected() && !anAccel && e->button() == Qt::MidButton ) )
1697         {
1698           myIsDragging = true;
1699           myStoredCursor = cursor();
1700           setCursor( Qt::ClosedHandCursor );
1701         }
1702       }
1703       break;
1704     }
1705     case QEvent::GraphicsSceneMouseMove:
1706     {
1707       if( hasInteractionFlag( EditFlags ) && nbSelected() )
1708         for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1709           if( GraphicsView_Object* anObject = selectedObject() )
1710             anIsHandled = anObject->handleMouseMove( e );
1711
1712       if( !anIsHandled && !isPulling() && myIsDragging )
1713         dragObjects( e );
1714       break;
1715     }
1716     case QEvent::GraphicsSceneMouseRelease:
1717     {
1718       if( hasInteractionFlag( EditFlags ) && nbSelected() )
1719         for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1720           if( GraphicsView_Object* anObject = selectedObject() )
1721             anIsHandled = anObject->handleMouseRelease( e );
1722
1723       if( !anIsHandled && !isPulling() && myIsDragging )
1724       {
1725         emit vpObjectBeforeMoving();
1726
1727         bool anIsMoved = false;
1728         for( initSelected(); moreSelected(); nextSelected() )
1729           if( GraphicsView_Object* aMovingObject = selectedObject() )
1730             anIsMoved = aMovingObject->finishMove( true ) || anIsMoved;
1731
1732         if( GraphicsView_Object* aMovingObject = getHighlightedObject() )
1733           anIsMoved = aMovingObject->finishMove( true ) || anIsMoved;
1734
1735         myIsDragging = false;
1736         myDragPosition = QPointF();
1737         setCursor( myStoredCursor );
1738
1739         emit vpObjectAfterMoving( anIsMoved );
1740       }
1741       break;
1742     }
1743     case QEvent::GraphicsSceneMouseDoubleClick:
1744       break; // do nothing, just emit the signal
1745     default:
1746       break;
1747   }
1748
1749   if( myIsMousePositionEnabled )
1750   {
1751     int aMouseX = (int)e->scenePos().x();
1752     int aMouseY = (int)e->scenePos().y();
1753     setViewLabelText( QString( "(%1, %2)" ).arg( aMouseX ).arg( aMouseY ) );
1754   }
1755 }
1756
1757 //================================================================
1758 // Function : onWheelEvent
1759 // Purpose  : 
1760 //================================================================
1761 void GraphicsView_ViewPort::onWheelEvent( QGraphicsSceneWheelEvent* e )
1762 {
1763   emit vpWheelEvent( e );
1764 }
1765
1766 //================================================================
1767 // Function : onContextMenuEvent
1768 // Purpose  : 
1769 //================================================================
1770 void GraphicsView_ViewPort::onContextMenuEvent( QGraphicsSceneContextMenuEvent* e )
1771 {
1772   emit vpContextMenuEvent( e );
1773 }
1774
1775 //================================================================
1776 // Function : scrollContentsBy
1777 // Purpose  : 
1778 //================================================================
1779 void GraphicsView_ViewPort::scrollContentsBy( int theDX, int theDY )
1780 {
1781   if( myViewLabel )
1782     myViewLabel->setAcceptMoveEvents( false );
1783
1784   QGraphicsView::scrollContentsBy( theDX, theDY );
1785
1786   if( myViewLabel )
1787     myViewLabel->setAcceptMoveEvents( true );
1788 }