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