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