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