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