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