Salome HOME
Copyright update: 2016
[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   // increasing of diagonal coefficients (>300) leads to a crash sometimes
854   // at the values of 100 some primitives are drawn incorrectly
855   if( qMax( aM11, aM22 ) < 100 )
856     setTransform( aTransform );
857
858   myIsTransforming = false;
859
860   applyTransform();
861 }
862
863 //================================================================
864 // Function : fitRect
865 // Purpose  : 
866 //================================================================
867 void GraphicsView_ViewPort::fitRect( const QRectF& theRect )
868 {
869   myIsTransforming = true;
870
871   fitInView( theRect, Qt::KeepAspectRatio );
872
873   myIsTransforming = false;
874
875   applyTransform();
876 }
877
878 //================================================================
879 // Function : fitSelect
880 // Purpose  : 
881 //================================================================
882 void GraphicsView_ViewPort::fitSelect()
883 {
884   myIsTransforming = true;
885
886   QRectF aGlobalRect;
887   for( initSelected(); moreSelected(); nextSelected() )
888   {
889     if( GraphicsView_Object* aMovingObject = selectedObject() )
890     {
891       QRectF aRect = aMovingObject->getRect();
892       if( aGlobalRect.isNull() )
893         aGlobalRect = aRect;
894       else
895         aGlobalRect |= aRect;
896     }
897   }
898
899   if( !aGlobalRect.isNull() )
900   {
901     double aGap = qMax( aGlobalRect.width(), aGlobalRect.height() ) / 5;
902     aGlobalRect.adjust( -aGap, -aGap, aGap, aGap );
903     fitInView( aGlobalRect, Qt::KeepAspectRatio );
904   }
905
906   myIsTransforming = false;
907
908   applyTransform();
909 }
910
911 //================================================================
912 // Function : fitAll
913 // Purpose  : 
914 //================================================================
915 void GraphicsView_ViewPort::fitAll( bool theKeepScale )
916 {
917   myIsTransforming = true;
918
919   if( theKeepScale )
920     myCurrentTransform = transform();
921
922   double aGap = myFitAllGap;
923   QRectF aRect = objectsBoundingRect( true );
924   fitInView( aRect.adjusted( -aGap, -aGap, aGap, aGap ), Qt::KeepAspectRatio );
925
926   myIsTransforming = false;
927
928   applyTransform();
929 }
930
931 //================================================================
932 // Function : fitWidth
933 // Purpose  : 
934 //================================================================
935 void GraphicsView_ViewPort::fitWidth()
936 {
937   myIsTransforming = true;
938
939   double aGap = myFitAllGap;
940   QRectF aRect = objectsBoundingRect( true );
941
942   double aTop = aRect.top();
943   double aLeft = aRect.left();
944   double aMargin = 10;
945
946   aRect.setY( aRect.center().y() );
947   aRect.setHeight( aMargin );
948
949   fitInView( aRect.adjusted( -aGap, -aGap, aGap, aGap ), Qt::KeepAspectRatio );
950   ensureVisible( aLeft, aTop, aMargin, aMargin, 0, aGap );
951
952   myIsTransforming = false;
953
954   applyTransform();
955 }
956
957 //================================================================
958 // Function : applyTransform
959 // Purpose  : 
960 //================================================================
961 void GraphicsView_ViewPort::applyTransform()
962 {
963   GraphicsView_ObjectListIterator anIter( getObjects() );
964   while( anIter.hasNext() )
965     if( GraphicsView_Object* anObject = anIter.next() )
966       anObject->setViewTransform( transform() );
967 }
968
969 //================================================================
970 // Function : currentBlock
971 // Purpose  : 
972 //================================================================
973 GraphicsView_ViewPort::BlockStatus GraphicsView_ViewPort::currentBlock()
974 {
975   if( isDragging() && !myDragPosition.isNull() )
976     return BlockStatus( BS_Selection );
977
978   if( myAreSelectionPointsInitialized && ( myFirstSelectionPoint != myLastSelectionPoint ) )
979     return BlockStatus( BS_Selection );
980
981   if( isPulling() )
982     return BlockStatus( BS_Selection );
983
984   return BS_NoBlock;
985 }
986
987 //================================================================
988 // Function : highlight
989 // Purpose  : 
990 //================================================================
991 void GraphicsView_ViewPort::highlight( double theX, double theY )
992 {
993   myIsHighlighting = true;
994   myHighlightX = theX;
995   myHighlightY = theY;
996
997   bool anIsHighlighted = false;
998   bool anIsOnObject = false;
999
1000   GraphicsView_Object* aPreviousHighlightedObject = myHighlightedObject;
1001   GraphicsView_Object* aHighlightedObject = 0;
1002
1003   QCursor aCursor;
1004
1005   GraphicsView_ObjectList aList = getObjects( SortByZLevel );
1006   GraphicsView_ObjectListIterator anIter( aList );
1007   anIter.toBack(); // objects with higher priority have to be checked earlier
1008   while( anIter.hasPrevious() )
1009   {
1010     if( GraphicsView_Object* anObject = anIter.previous() )
1011     {
1012       if( anObject->isVisible() && anObject->isSelectable() )
1013       {
1014         if( anObject->checkHighlight( theX, theY, aCursor ) )
1015         {
1016           anIsOnObject = true;
1017           anIsHighlighted = anObject->highlight( theX, theY );
1018         }
1019
1020         if( anIsHighlighted )
1021         {
1022           aHighlightedObject = anObject;
1023           break;
1024         }
1025       }
1026     }
1027   }
1028
1029   setCursor( aCursor );
1030
1031   if( !anIsOnObject )
1032   {
1033     anIter = aList;
1034     while( anIter.hasNext() )
1035       if( GraphicsView_Object* anObject = anIter.next() )
1036         anObject->unhighlight();
1037
1038     myHighlightedObject = 0;
1039     return;
1040   }
1041   else if( !myHighlightedObject && anIsHighlighted )
1042   {
1043     myHighlightedObject = aHighlightedObject;
1044   }
1045   else if( myHighlightedObject && !anIsHighlighted )
1046   {
1047     myHighlightedObject->unhighlight();
1048     myHighlightedObject = 0;
1049   }
1050   else if( myHighlightedObject && anIsHighlighted )
1051   {
1052     myHighlightedObject->highlight( theX, theY );
1053     if( myHighlightedObject != aHighlightedObject )
1054     {
1055       myHighlightedObject->unhighlight();
1056       myHighlightedObject = aHighlightedObject;
1057     }
1058   }
1059 }
1060
1061 //================================================================
1062 // Function : clearHighlighted
1063 // Purpose  : 
1064 //================================================================
1065 void GraphicsView_ViewPort::clearHighlighted()
1066 {
1067   if( myHighlightedObject )
1068   {
1069     myHighlightedObject->unhighlight();
1070     myHighlightedObject = 0;
1071   }
1072 }
1073
1074 //================================================================
1075 // Function : select
1076 // Purpose  : 
1077 //================================================================
1078 int GraphicsView_ViewPort::select( const QRectF& theRect, bool theIsAppend )
1079 {
1080   if( !myIsHighlighting )
1081     return GVSS_NoChanged;
1082
1083   GV_SelectionStatus aStatus = GVSS_Invalid;
1084   if( theRect.isNull() ) // point selection
1085   {
1086     if( myHighlightedObject )
1087     {
1088       if( mySelectedObjects.count() == 1 &&
1089           mySelectedObjects.first() == myHighlightedObject )
1090         aStatus = GVSS_LocalChanged;
1091
1092       if( !theIsAppend )
1093       {
1094         GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1095         while( anIter.hasNext() )
1096           if( GraphicsView_Object* anObject = anIter.next() )
1097             if( myHighlightedObject != anObject )
1098               anObject->unselect();
1099
1100         if( !mySelectedObjects.isEmpty() && aStatus == GVSS_Invalid )
1101           aStatus = GVSS_GlobalChanged;
1102         mySelectedObjects.clear();
1103       } 
1104       else if( myHighlightedObject->isSelected() && aStatus != GVSS_LocalChanged )
1105       {
1106         mySelectedObjects.removeAll( myHighlightedObject );
1107         myHighlightedObject->unselect();
1108
1109         if( !mySelectedObjects.isEmpty() && aStatus == GVSS_Invalid )
1110           aStatus = GVSS_GlobalChanged;
1111
1112         return aStatus;
1113       }
1114
1115       if( myHighlightedObject->select( myHighlightX, myHighlightY, QRectF() ) &&
1116           mySelectedObjects.indexOf( myHighlightedObject ) == -1 )
1117       {
1118         mySelectedObjects.append( myHighlightedObject );
1119         if( aStatus == GVSS_Invalid )
1120           aStatus = GVSS_GlobalChanged;
1121       }
1122       else if( aStatus == GVSS_LocalChanged )
1123         aStatus = GVSS_GlobalChanged;
1124
1125       return aStatus;
1126     }
1127
1128     if( !myHighlightedObject )
1129     {
1130       if( !theIsAppend )
1131       {
1132         GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1133         while( anIter.hasNext() )
1134           if( GraphicsView_Object* anObject = anIter.next() )
1135             if( myHighlightedObject != anObject )
1136               anObject->unselect();
1137
1138         if( !mySelectedObjects.isEmpty() )
1139           aStatus = GVSS_GlobalChanged;
1140         mySelectedObjects.clear();
1141       }
1142       return aStatus;
1143     }
1144
1145     return GVSS_NoChanged;
1146   }
1147   else // rectangle selection
1148   {
1149     aStatus = GVSS_NoChanged;
1150
1151     bool updateAll = false;
1152     if( !theIsAppend )
1153     {
1154       if( !mySelectedObjects.isEmpty() )
1155         aStatus = GVSS_GlobalChanged;
1156
1157       GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1158       while( anIter.hasNext() )
1159         if( GraphicsView_Object* anObject = anIter.next() )
1160           if( myHighlightedObject != anObject )
1161             anObject->unselect();
1162       mySelectedObjects.clear();
1163     }
1164
1165     QListIterator<QGraphicsItem*> anIter( items() );
1166     while( anIter.hasNext() )
1167     {
1168       if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1169       {
1170         if( anObject->isVisible() && anObject->isSelectable() )
1171         {
1172           bool anIsSelected = false;
1173           QRectF aRect = anObject->getRect();
1174           if( theRect.contains( aRect ) && myIsHighlighting )
1175             anIsSelected = anObject->select( myHighlightX, myHighlightY, theRect );
1176
1177           if( anIsSelected && mySelectedObjects.indexOf( anObject ) == -1 )
1178           {
1179             mySelectedObjects.append( anObject );
1180             aStatus = GVSS_GlobalChanged;
1181           }
1182         }
1183       }
1184     }
1185   }
1186   return aStatus;
1187 }
1188
1189 //================================================================
1190 // Function : clearSelected
1191 // Purpose  : 
1192 //================================================================
1193 void GraphicsView_ViewPort::clearSelected()
1194 {
1195   GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1196   while( anIter.hasNext() )
1197     if( GraphicsView_Object* anObject = anIter.next() )
1198       anObject->unselect();
1199   mySelectedObjects.clear();
1200 }
1201
1202 //================================================================
1203 // Function : setSelected
1204 // Purpose  : 
1205 //================================================================
1206 void GraphicsView_ViewPort::setSelected( GraphicsView_Object* theObject )
1207 {
1208   if( theObject )
1209   {
1210     theObject->setSelected( true );
1211     mySelectedObjects.append( theObject );
1212   }
1213 }
1214
1215 //================================================================
1216 // Function : nbSelected
1217 // Purpose  : 
1218 //================================================================
1219 int GraphicsView_ViewPort::nbSelected() const
1220 {
1221   return mySelectedObjects.count();
1222 }
1223
1224 //================================================================
1225 // Function : initSelected
1226 // Purpose  : 
1227 //================================================================
1228 void GraphicsView_ViewPort::initSelected()
1229 {
1230   mySelectionIterator = 0;
1231 }
1232
1233 //================================================================
1234 // Function : moreSelected
1235 // Purpose  : 
1236 //================================================================
1237 bool GraphicsView_ViewPort::moreSelected()
1238 {
1239   return mySelectionIterator < nbSelected();
1240 }
1241
1242 //================================================================
1243 // Function : nextSelected
1244 // Purpose  : 
1245 //================================================================
1246 bool GraphicsView_ViewPort::nextSelected()
1247 {
1248   if( mySelectionIterator >= 0 && mySelectionIterator < nbSelected() )
1249   {
1250     mySelectionIterator++;
1251     return true;
1252   }
1253   return false;
1254 }
1255
1256 //================================================================
1257 // Function : selectedObject
1258 // Purpose  : 
1259 //================================================================
1260 GraphicsView_Object* GraphicsView_ViewPort::selectedObject()
1261 {
1262   if( mySelectionIterator >= 0 && mySelectionIterator < nbSelected() )
1263     return mySelectedObjects[ mySelectionIterator ];
1264   return 0;
1265 }
1266
1267 //================================================================
1268 // Function : startSelectByRect
1269 // Purpose  : 
1270 //================================================================
1271 void GraphicsView_ViewPort::startSelectByRect( int x, int y )
1272 {
1273   if( !myAreSelectionPointsInitialized )
1274   {
1275     myFirstSelectionPoint = QPoint( x, y );
1276     myLastSelectionPoint = QPoint( x, y );
1277     myAreSelectionPointsInitialized = true;
1278   }
1279
1280   if( !myRectBand )
1281   {
1282     myRectBand = new QRubberBand( QRubberBand::Rectangle, this );
1283     QPalette palette;
1284     palette.setColor( myRectBand->foregroundRole(), Qt::white );
1285     myRectBand->setPalette( palette );
1286   }
1287   myRectBand->hide();
1288 }
1289
1290 //================================================================
1291 // Function : drawSelectByRect
1292 // Purpose  : 
1293 //================================================================
1294 void GraphicsView_ViewPort::drawSelectByRect( int x, int y )
1295 {
1296   if( myAreSelectionPointsInitialized )
1297   {
1298     myRectBand->hide();
1299
1300     myLastSelectionPoint.setX( x );
1301     myLastSelectionPoint.setY( y );
1302
1303     QRect aRect = selectionRect();
1304     myRectBand->setGeometry( aRect );
1305     myRectBand->setVisible( aRect.isValid() );
1306   }
1307 }
1308
1309 //================================================================
1310 // Function : isSelectByRect
1311 // Purpose  : 
1312 //================================================================
1313 bool GraphicsView_ViewPort::isSelectByRect() const
1314 {
1315   return myAreSelectionPointsInitialized;
1316 }
1317
1318 //================================================================
1319 // Function : finishSelectByRect
1320 // Purpose  : 
1321 //================================================================
1322 void GraphicsView_ViewPort::finishSelectByRect()
1323 {
1324   if( myAreSelectionPointsInitialized )
1325   {
1326     if( myRectBand )
1327     {
1328       myRectBand->hide();
1329       delete myRectBand;
1330       myRectBand = 0;
1331     }
1332
1333     myAreSelectionPointsInitialized = false;
1334   }
1335 }
1336
1337 //================================================================
1338 // Function : selectionRect
1339 // Purpose  : 
1340 //================================================================
1341 QRect GraphicsView_ViewPort::selectionRect()
1342 {
1343   QRect aRect;
1344   if( myAreSelectionPointsInitialized )
1345   {
1346     aRect.setLeft( qMin( myFirstSelectionPoint.x(), myLastSelectionPoint.x() ) );
1347     aRect.setTop( qMin( myFirstSelectionPoint.y(), myLastSelectionPoint.y() ) );
1348     aRect.setRight( qMax( myFirstSelectionPoint.x(), myLastSelectionPoint.x() ) );
1349     aRect.setBottom( qMax( myFirstSelectionPoint.y(), myLastSelectionPoint.y() ) );
1350   }
1351   return aRect;
1352 }
1353
1354 //================================================================
1355 // Function : prepareToSketch
1356 // Purpose  : 
1357 //================================================================
1358 void GraphicsView_ViewPort::prepareToSketch( bool theStatus )
1359 {
1360   myIsPrepareToSketch = theStatus;
1361   if( theStatus )
1362     setCursor( *getSketchCursor() );
1363 }
1364
1365 //================================================================
1366 // Function : isPrepareToSketch
1367 // Purpose  : 
1368 //================================================================
1369 bool GraphicsView_ViewPort::isPrepareToSketch()
1370 {
1371   return myIsPrepareToSketch;
1372 }
1373
1374 //================================================================
1375 // Function : startSketching
1376 // Purpose  : 
1377 //================================================================
1378 void GraphicsView_ViewPort::startSketching( const QPointF& thePoint,
1379                                             bool theIsPath )
1380 {
1381   prepareToSketch( false );
1382
1383   if( !mySketchingItem )
1384   {
1385     mySketchingItem = new QGraphicsPathItem();
1386     mySketchingItem->setZValue( SKETCH_Z_VALUE );
1387
1388     QPen aPen = mySketchingItem->pen();
1389     aPen.setStyle( Qt::DotLine );
1390     mySketchingItem->setPen( aPen );
1391
1392     addItem( mySketchingItem );
1393   }
1394
1395   mySketchingPoint = thePoint;
1396
1397   QPainterPath aPath;
1398   aPath.moveTo( mySketchingPoint );
1399   mySketchingItem->setPath( aPath );
1400   mySketchingItem->setVisible( true );
1401
1402   myIsSketching = true;
1403   myIsSketchingByPath = theIsPath;
1404 }
1405
1406 //================================================================
1407 // Function : drawSketching
1408 // Purpose  : 
1409 //================================================================
1410 void GraphicsView_ViewPort::drawSketching( const QPointF& thePoint )
1411 {
1412   bool anIsPath = false;
1413   if( mySketchingItem && isSketching( &anIsPath ) )
1414   {
1415     QPainterPath aPath = mySketchingItem->path();
1416     if( anIsPath ) // arbitrary path
1417       aPath.lineTo( thePoint );
1418     else // rectangle
1419     {
1420       // make a valid rectangle
1421       double x1 = mySketchingPoint.x(), y1 = mySketchingPoint.y();
1422       double x2 = thePoint.x(), y2 = thePoint.y();
1423       QPointF aPoint1( qMin( x1, x2 ), qMin( y1, y2 ) );
1424       QPointF aPoint2( qMax( x1, x2 ), qMax( y1, y2 ) );
1425       QRectF aRect( aPoint1, aPoint2 );
1426
1427       aPath = QPainterPath();
1428       aPath.addRect( aRect );
1429     }
1430     mySketchingItem->setPath( aPath );
1431   }
1432 }
1433
1434 //================================================================
1435 // Function : finishSketching
1436 // Purpose  : 
1437 //================================================================
1438 void GraphicsView_ViewPort::finishSketching( bool theStatus )
1439 {
1440   prepareToSketch( false );
1441
1442   mySketchingItem->setVisible( false );
1443   myIsSketching = false;
1444
1445   setCursor( *getDefaultCursor() );
1446
1447   if( theStatus )
1448   {
1449     QPainterPath aPath = mySketchingItem->path();
1450     emit vpSketchingFinished( aPath );
1451   }
1452 }
1453
1454 //================================================================
1455 // Function : isSketching
1456 // Purpose  : 
1457 //================================================================
1458 bool GraphicsView_ViewPort::isSketching( bool* theIsPath ) const
1459 {
1460   if( theIsPath )
1461     *theIsPath = myIsSketchingByPath;
1462   return myIsSketching;
1463 }
1464
1465 //================================================================
1466 // Function : dragObjects
1467 // Purpose  : 
1468 //================================================================
1469 void GraphicsView_ViewPort::dragObjects( QGraphicsSceneMouseEvent* e )
1470 {
1471   GraphicsView_Object* anObject = getHighlightedObject();
1472
1473   if( myDragPosition.isNull() )
1474   {
1475     myDragPosition = e->scenePos();
1476     return;
1477   }
1478
1479   GraphicsView_ObjectList anObjectsToMove;
1480   if( anObject && anObject->isMovable() && ( e->buttons() & Qt::LeftButton ) )
1481   {
1482     if( anObject->isSelected() )
1483     {
1484       for( initSelected(); moreSelected(); nextSelected() )
1485         if( GraphicsView_Object* aMovingObject = selectedObject() )
1486           if( aMovingObject->isMovable() )
1487             anObjectsToMove.append( aMovingObject );
1488     }
1489     else
1490       anObjectsToMove.append( anObject );
1491   }
1492   else if( hasInteractionFlag( DraggingByMiddleButton ) &&
1493            nbSelected() && ( e->buttons() & Qt::MidButton ) )
1494   {
1495     for( initSelected(); moreSelected(); nextSelected() )
1496       if( GraphicsView_Object* aMovingObject = selectedObject() )
1497         if( aMovingObject->isMovable() )
1498           anObjectsToMove.append( aMovingObject );
1499   }
1500
1501   if( anObjectsToMove.isEmpty() )
1502     return;
1503
1504   double aDX = e->scenePos().x() - myDragPosition.x();
1505   double aDY = e->scenePos().y() - myDragPosition.y();
1506
1507   bool anIsMovingByXAllowed = true, anIsMovingByYAllowed = true;
1508   GraphicsView_ObjectListIterator anIter( anObjectsToMove );
1509   while( anIter.hasNext() )
1510     if( GraphicsView_Object* aMovingObject = anIter.next() )
1511     {
1512       if( !aMovingObject->isMovingByXAllowed( aDX ) )
1513         anIsMovingByXAllowed = false;
1514       if( !aMovingObject->isMovingByYAllowed( aDY ) )
1515         anIsMovingByYAllowed = false;
1516     }
1517
1518   if( !anIsMovingByXAllowed && !anIsMovingByYAllowed )
1519     return; // myDragPosition shouldn't be changed
1520
1521   if( !anIsMovingByXAllowed )
1522     aDX = 0;
1523
1524   if( !anIsMovingByYAllowed )
1525     aDY = 0;
1526
1527   anIter = anObjectsToMove;
1528   while( anIter.hasNext() )
1529     if( GraphicsView_Object* aMovingObject = anIter.next() )
1530       aMovingObject->move( aDX, aDY );
1531
1532   if( anIsMovingByXAllowed )
1533     myDragPosition.setX( e->scenePos().x() );
1534
1535   if( anIsMovingByYAllowed )
1536     myDragPosition.setY( e->scenePos().y() );
1537 }
1538
1539 //================================================================
1540 // Function : startPulling
1541 // Purpose  : 
1542 //================================================================
1543 bool GraphicsView_ViewPort::startPulling( const QPointF& thePoint )
1544 {
1545   QListIterator<QGraphicsItem*> anIter( items() );
1546   while( anIter.hasNext() )
1547   {
1548     if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1549     {
1550       QRectF aRect = anObject->getPullingRect();
1551       if( aRect.contains( thePoint ) && anObject->startPulling( thePoint ) )
1552       {
1553         myIsPulling = true;
1554         myPullingObject = anObject;
1555         //setCursor( *getHandCursor() ); // testing ImageViewer
1556         return true;
1557       }
1558     }
1559   }
1560   return false;
1561 }
1562
1563 //================================================================
1564 // Function : drawPulling
1565 // Purpose  : 
1566 //================================================================
1567 void GraphicsView_ViewPort::drawPulling( const QPointF& thePoint )
1568 {
1569   GraphicsView_Object* aLockedObject = 0;
1570
1571   QListIterator<QGraphicsItem*> anIter( items() );
1572   while( anIter.hasNext() )
1573   {
1574     if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1575     {
1576       if( !anObject->isVisible() )
1577         continue;
1578
1579       QRectF aRect = anObject->getPullingRect();
1580       if( aRect.contains( thePoint ) && anObject->portContains( thePoint ) )
1581       {
1582         aLockedObject = anObject;
1583         break;
1584       }
1585     }
1586   }
1587
1588   myPullingObject->pull( thePoint, aLockedObject, getSelectedObjects() );
1589 }
1590
1591 //================================================================
1592 // Function : finishPulling
1593 // Purpose  : 
1594 //================================================================
1595 void GraphicsView_ViewPort::finishPulling( bool theStatus )
1596 {
1597   myIsPulling = false;
1598   myPullingObject->finishPulling( theStatus, getSelectedObjects() );
1599   setCursor( *getDefaultCursor() );
1600 }
1601
1602 //================================================================
1603 // Function : cancelCurrentOperation
1604 // Purpose  : 
1605 //================================================================
1606 bool GraphicsView_ViewPort::cancelCurrentOperation()
1607 {
1608   myIsHighlighting = false;
1609
1610   if( isDragging() )
1611   {
1612     for( initSelected(); moreSelected(); nextSelected() )
1613       if( GraphicsView_Object* aMovingObject = selectedObject() )
1614         aMovingObject->finishMove( false );
1615
1616     if( GraphicsView_Object* aMovingObject = getHighlightedObject() )
1617       aMovingObject->finishMove( false );
1618
1619     myIsDragging = false;
1620     myDragPosition = QPointF();
1621     //setCursor( myStoredCursor );
1622     setCursor( *getDefaultCursor() );
1623
1624     return true;
1625   }
1626
1627   if( isPulling() )
1628   {
1629     finishPulling( false );
1630     return true;
1631   }
1632
1633   if( isSketching() || isPrepareToSketch() )
1634   {
1635     finishSketching( false );
1636     return true;
1637   }
1638
1639   return false;
1640 }
1641
1642 //================================================================
1643 // Function : onBoundingRectChanged
1644 // Purpose  : 
1645 //================================================================
1646 void GraphicsView_ViewPort::onBoundingRectChanged()
1647 {
1648   if( hasInteractionFlag( TraceBoundingRect ) )
1649   {
1650     QRectF aRect = objectsBoundingRect( true );
1651     myScene->setSceneRect( aRect.adjusted( -mySceneGap, -mySceneGap, mySceneGap, mySceneGap ) );
1652   }
1653 }
1654
1655 //================================================================
1656 // Function : onKeyEvent
1657 // Purpose  : 
1658 //================================================================
1659 void GraphicsView_ViewPort::onKeyEvent( QKeyEvent* e )
1660 {
1661   emit vpKeyEvent( e );
1662 }
1663
1664 //================================================================
1665 // Function : onMouseEvent
1666 // Purpose  : 
1667 //================================================================
1668 void GraphicsView_ViewPort::onMouseEvent( QGraphicsSceneMouseEvent* e )
1669 {
1670   emit vpMouseEvent( e );
1671
1672   bool anIsHandled = false;
1673   switch( e->type() )
1674   {
1675     case QEvent::GraphicsSceneMousePress:
1676     {
1677       if( hasInteractionFlag( EditFlags ) && nbSelected() )
1678         for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1679           if( GraphicsView_Object* anObject = selectedObject() )
1680             anIsHandled = anObject->handleMousePress( e );
1681
1682       if( !anIsHandled && hasInteractionFlag( Dragging ) )
1683       {
1684         bool anAccel = e->modifiers() & GraphicsView_ViewTransformer::accelKey();
1685         if( ( getHighlightedObject() &&
1686               getHighlightedObject()->isMovable() &&
1687               !( anAccel || e->button() != Qt::LeftButton ) ) ||
1688             ( hasInteractionFlag( DraggingByMiddleButton ) &&
1689               nbSelected() && !anAccel && e->button() == Qt::MidButton ) )
1690         {
1691           myIsDragging = true;
1692           myStoredCursor = cursor();
1693           setCursor( Qt::ClosedHandCursor );
1694         }
1695       }
1696       break;
1697     }
1698     case QEvent::GraphicsSceneMouseMove:
1699     {
1700       if( hasInteractionFlag( EditFlags ) && nbSelected() )
1701         for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1702           if( GraphicsView_Object* anObject = selectedObject() )
1703             anIsHandled = anObject->handleMouseMove( e );
1704
1705       if( !anIsHandled && !isPulling() && myIsDragging )
1706         dragObjects( e );
1707       break;
1708     }
1709     case QEvent::GraphicsSceneMouseRelease:
1710     {
1711       if( hasInteractionFlag( EditFlags ) && nbSelected() )
1712         for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1713           if( GraphicsView_Object* anObject = selectedObject() )
1714             anIsHandled = anObject->handleMouseRelease( e );
1715
1716       if( !anIsHandled && !isPulling() && myIsDragging )
1717       {
1718         emit vpObjectBeforeMoving();
1719
1720         bool anIsMoved = false;
1721         for( initSelected(); moreSelected(); nextSelected() )
1722           if( GraphicsView_Object* aMovingObject = selectedObject() )
1723             anIsMoved = aMovingObject->finishMove( true ) || anIsMoved;
1724
1725         if( GraphicsView_Object* aMovingObject = getHighlightedObject() )
1726           anIsMoved = aMovingObject->finishMove( true ) || anIsMoved;
1727
1728         myIsDragging = false;
1729         myDragPosition = QPointF();
1730         setCursor( myStoredCursor );
1731
1732         emit vpObjectAfterMoving( anIsMoved );
1733       }
1734       break;
1735     }
1736     case QEvent::GraphicsSceneMouseDoubleClick:
1737       break; // do nothing, just emit the signal
1738     default:
1739       break;
1740   }
1741
1742   if( myIsMousePositionEnabled )
1743   {
1744     int aMouseX = (int)e->scenePos().x();
1745     int aMouseY = (int)e->scenePos().y();
1746     setViewLabelText( QString( "(%1, %2)" ).arg( aMouseX ).arg( aMouseY ) );
1747   }
1748 }
1749
1750 //================================================================
1751 // Function : onWheelEvent
1752 // Purpose  : 
1753 //================================================================
1754 void GraphicsView_ViewPort::onWheelEvent( QGraphicsSceneWheelEvent* e )
1755 {
1756   emit vpWheelEvent( e );
1757 }
1758
1759 //================================================================
1760 // Function : onContextMenuEvent
1761 // Purpose  : 
1762 //================================================================
1763 void GraphicsView_ViewPort::onContextMenuEvent( QGraphicsSceneContextMenuEvent* e )
1764 {
1765   emit vpContextMenuEvent( e );
1766 }
1767
1768 //================================================================
1769 // Function : scrollContentsBy
1770 // Purpose  : 
1771 //================================================================
1772 void GraphicsView_ViewPort::scrollContentsBy( int theDX, int theDY )
1773 {
1774   if( myViewLabel )
1775     myViewLabel->setAcceptMoveEvents( false );
1776
1777   QGraphicsView::scrollContentsBy( theDX, theDY );
1778
1779   if( myViewLabel )
1780     myViewLabel->setAcceptMoveEvents( true );
1781 }