Salome HOME
redesign of the export to PostScript
[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   printer.setOutputFormat(QPrinter::PostScriptFormat);
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   // increasing of diagonal coefficients (>300) leads to a crash sometimes
919   // at the values of 100 some primitives are drawn incorrectly
920   if( myZoomCoeff < 0 || qMax( aM11, aM22 ) < myZoomCoeff )
921     setTransform( aTransform );
922
923   myIsTransforming = false;
924
925   applyTransform();
926 }
927
928 //================================================================
929 // Function : fitRect
930 // Purpose  : 
931 //================================================================
932 void GraphicsView_ViewPort::fitRect( const QRectF& theRect )
933 {
934   myIsTransforming = true;
935
936   fitInView( theRect, Qt::KeepAspectRatio );
937
938   myIsTransforming = false;
939
940   applyTransform();
941 }
942
943 //================================================================
944 // Function : fitSelect
945 // Purpose  : 
946 //================================================================
947 void GraphicsView_ViewPort::fitSelect()
948 {
949   myIsTransforming = true;
950
951   QRectF aGlobalRect;
952   for( initSelected(); moreSelected(); nextSelected() )
953   {
954     if( GraphicsView_Object* aMovingObject = selectedObject() )
955     {
956       QRectF aRect = aMovingObject->getRect();
957       if( aGlobalRect.isNull() )
958         aGlobalRect = aRect;
959       else
960         aGlobalRect |= aRect;
961     }
962   }
963
964   if( !aGlobalRect.isNull() )
965   {
966     double aGap = qMax( aGlobalRect.width(), aGlobalRect.height() ) / 5;
967     aGlobalRect.adjust( -aGap, -aGap, aGap, aGap );
968     fitInView( aGlobalRect, Qt::KeepAspectRatio );
969   }
970
971   myIsTransforming = false;
972
973   applyTransform();
974 }
975
976 //================================================================
977 // Function : fitAll
978 // Purpose  : 
979 //================================================================
980 void GraphicsView_ViewPort::fitAll( bool theKeepScale )
981 {
982   myIsTransforming = true;
983
984   if( theKeepScale )
985     myCurrentTransform = transform();
986
987   double aGap = myFitAllGap;
988   QRectF aRect = objectsBoundingRect( true );
989   fitInView( aRect.adjusted( -aGap, -aGap, aGap, aGap ), Qt::KeepAspectRatio );
990
991   myIsTransforming = false;
992
993   applyTransform();
994 }
995
996 //================================================================
997 // Function : fitWidth
998 // Purpose  : 
999 //================================================================
1000 void GraphicsView_ViewPort::fitWidth()
1001 {
1002   myIsTransforming = true;
1003
1004   double aGap = myFitAllGap;
1005   QRectF aRect = objectsBoundingRect( true );
1006
1007   double aTop = aRect.top();
1008   double aLeft = aRect.left();
1009   double aMargin = 10;
1010
1011   aRect.setY( aRect.center().y() );
1012   aRect.setHeight( aMargin );
1013
1014   fitInView( aRect.adjusted( -aGap, -aGap, aGap, aGap ), Qt::KeepAspectRatio );
1015   ensureVisible( aLeft, aTop, aMargin, aMargin, 0, aGap );
1016
1017   myIsTransforming = false;
1018
1019   applyTransform();
1020 }
1021
1022 //================================================================
1023 // Function : applyTransform
1024 // Purpose  : 
1025 //================================================================
1026 void GraphicsView_ViewPort::applyTransform()
1027 {
1028   GraphicsView_ObjectListIterator anIter( getObjects() );
1029   while( anIter.hasNext() )
1030     if( GraphicsView_Object* anObject = anIter.next() )
1031       anObject->setViewTransform( transform() );
1032 }
1033
1034 //================================================================
1035 // Function : setZoomCoeff
1036 // Purpose  : 
1037 //================================================================
1038 void GraphicsView_ViewPort::setZoomCoeff( const int& theZoomCoeff )
1039 {
1040   myZoomCoeff = theZoomCoeff;
1041 }
1042
1043 //================================================================
1044 // Function : setUnlimitedPanning
1045 // Purpose  : 
1046 //================================================================
1047 void GraphicsView_ViewPort::setUnlimitedPanning( const bool& theValue )
1048 {
1049   myUnlimitedPanning = theValue;
1050
1051   if( myUnlimitedPanning )
1052   {
1053     myHBarPolicy = horizontalScrollBarPolicy();
1054     myVBarPolicy = verticalScrollBarPolicy();
1055
1056     setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
1057     setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
1058   }
1059   else
1060   {
1061     setHorizontalScrollBarPolicy( myHBarPolicy );
1062     setVerticalScrollBarPolicy( myVBarPolicy );
1063   }
1064 }
1065
1066 //================================================================
1067 // Function : currentBlock
1068 // Purpose  : 
1069 //================================================================
1070 GraphicsView_ViewPort::BlockStatus GraphicsView_ViewPort::currentBlock()
1071 {
1072   if( isDragging() && !myDragPosition.isNull() )
1073     return BlockStatus( BS_Selection );
1074
1075   if( myAreSelectionPointsInitialized && ( myFirstSelectionPoint != myLastSelectionPoint ) )
1076     return BlockStatus( BS_Selection );
1077
1078   if( isPulling() )
1079     return BlockStatus( BS_Selection );
1080
1081   return BS_NoBlock;
1082 }
1083
1084 //================================================================
1085 // Function : highlight
1086 // Purpose  : 
1087 //================================================================
1088 void GraphicsView_ViewPort::highlight( double theX, double theY )
1089 {
1090   myIsHighlighting = true;
1091   myHighlightX = theX;
1092   myHighlightY = theY;
1093
1094   bool anIsHighlighted = false;
1095   bool anIsOnObject = false;
1096
1097   GraphicsView_Object* aPreviousHighlightedObject = myHighlightedObject;
1098   GraphicsView_Object* aHighlightedObject = 0;
1099
1100   QCursor aCursor;
1101
1102   GraphicsView_ObjectList aList = getObjects( SortByZLevel );
1103   GraphicsView_ObjectListIterator anIter( aList );
1104   anIter.toBack(); // objects with higher priority have to be checked earlier
1105   while( anIter.hasPrevious() )
1106   {
1107     if( GraphicsView_Object* anObject = anIter.previous() )
1108     {
1109       if( anObject->isVisible() && anObject->isSelectable() )
1110       {
1111         if( anObject->checkHighlight( theX, theY, aCursor ) )
1112         {
1113           anIsOnObject = true;
1114           anIsHighlighted = anObject->highlight( theX, theY );
1115         }
1116
1117         if( anIsHighlighted )
1118         {
1119           aHighlightedObject = anObject;
1120           break;
1121         }
1122       }
1123     }
1124   }
1125
1126   setCursor( aCursor );
1127
1128   if( !anIsOnObject )
1129   {
1130     anIter = aList;
1131     while( anIter.hasNext() )
1132       if( GraphicsView_Object* anObject = anIter.next() )
1133         anObject->unhighlight();
1134
1135     myHighlightedObject = 0;
1136     return;
1137   }
1138   else if( !myHighlightedObject && anIsHighlighted )
1139   {
1140     myHighlightedObject = aHighlightedObject;
1141   }
1142   else if( myHighlightedObject && !anIsHighlighted )
1143   {
1144     myHighlightedObject->unhighlight();
1145     myHighlightedObject = 0;
1146   }
1147   else if( myHighlightedObject && anIsHighlighted )
1148   {
1149     myHighlightedObject->highlight( theX, theY );
1150     if( myHighlightedObject != aHighlightedObject )
1151     {
1152       myHighlightedObject->unhighlight();
1153       myHighlightedObject = aHighlightedObject;
1154     }
1155   }
1156 }
1157
1158 //================================================================
1159 // Function : clearHighlighted
1160 // Purpose  : 
1161 //================================================================
1162 void GraphicsView_ViewPort::clearHighlighted()
1163 {
1164   if( myHighlightedObject )
1165   {
1166     myHighlightedObject->unhighlight();
1167     myHighlightedObject = 0;
1168   }
1169 }
1170
1171 //================================================================
1172 // Function : select
1173 // Purpose  : 
1174 //================================================================
1175 int GraphicsView_ViewPort::select( const QRectF& theRect, bool theIsAppend )
1176 {
1177   if( !myIsHighlighting )
1178     return GVSS_NoChanged;
1179
1180   GV_SelectionStatus aStatus = GVSS_Invalid;
1181   if( theRect.isNull() ) // point selection
1182   {
1183     if( myHighlightedObject )
1184     {
1185       if( mySelectedObjects.count() == 1 &&
1186           mySelectedObjects.first() == myHighlightedObject )
1187         aStatus = GVSS_LocalChanged;
1188
1189       if( !theIsAppend )
1190       {
1191         GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1192         while( anIter.hasNext() )
1193           if( GraphicsView_Object* anObject = anIter.next() )
1194             if( myHighlightedObject != anObject )
1195               anObject->unselect();
1196
1197         if( !mySelectedObjects.isEmpty() && aStatus == GVSS_Invalid )
1198           aStatus = GVSS_GlobalChanged;
1199         mySelectedObjects.clear();
1200       } 
1201       else if( myHighlightedObject->isSelected() && aStatus != GVSS_LocalChanged )
1202       {
1203         mySelectedObjects.removeAll( myHighlightedObject );
1204         myHighlightedObject->unselect();
1205
1206         if( !mySelectedObjects.isEmpty() && aStatus == GVSS_Invalid )
1207           aStatus = GVSS_GlobalChanged;
1208
1209         return aStatus;
1210       }
1211
1212       if( myHighlightedObject->select( myHighlightX, myHighlightY, QRectF() ) &&
1213           mySelectedObjects.indexOf( myHighlightedObject ) == -1 )
1214       {
1215         mySelectedObjects.append( myHighlightedObject );
1216         if( aStatus == GVSS_Invalid )
1217           aStatus = GVSS_GlobalChanged;
1218       }
1219       else if( aStatus == GVSS_LocalChanged )
1220         aStatus = GVSS_GlobalChanged;
1221
1222       return aStatus;
1223     }
1224
1225     if( !myHighlightedObject )
1226     {
1227       if( !theIsAppend )
1228       {
1229         GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1230         while( anIter.hasNext() )
1231           if( GraphicsView_Object* anObject = anIter.next() )
1232             if( myHighlightedObject != anObject )
1233               anObject->unselect();
1234
1235         if( !mySelectedObjects.isEmpty() )
1236           aStatus = GVSS_GlobalChanged;
1237         mySelectedObjects.clear();
1238       }
1239       return aStatus;
1240     }
1241
1242     return GVSS_NoChanged;
1243   }
1244   else // rectangle selection
1245   {
1246     aStatus = GVSS_NoChanged;
1247
1248     bool updateAll = false;
1249     if( !theIsAppend )
1250     {
1251       if( !mySelectedObjects.isEmpty() )
1252         aStatus = GVSS_GlobalChanged;
1253
1254       GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1255       while( anIter.hasNext() )
1256         if( GraphicsView_Object* anObject = anIter.next() )
1257           if( myHighlightedObject != anObject )
1258             anObject->unselect();
1259       mySelectedObjects.clear();
1260     }
1261
1262     QListIterator<QGraphicsItem*> anIter( items() );
1263     while( anIter.hasNext() )
1264     {
1265       if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1266       {
1267         if( anObject->isVisible() && anObject->isSelectable() )
1268         {
1269           bool anIsSelected = false;
1270           QRectF aRect = anObject->getRect();
1271           if( theRect.contains( aRect ) && myIsHighlighting )
1272             anIsSelected = anObject->select( myHighlightX, myHighlightY, theRect );
1273
1274           if( anIsSelected && mySelectedObjects.indexOf( anObject ) == -1 )
1275           {
1276             mySelectedObjects.append( anObject );
1277             aStatus = GVSS_GlobalChanged;
1278           }
1279         }
1280       }
1281     }
1282   }
1283   return aStatus;
1284 }
1285
1286 //================================================================
1287 // Function : clearSelected
1288 // Purpose  : 
1289 //================================================================
1290 void GraphicsView_ViewPort::clearSelected()
1291 {
1292   GraphicsView_ObjectListIterator anIter( mySelectedObjects );
1293   while( anIter.hasNext() )
1294     if( GraphicsView_Object* anObject = anIter.next() )
1295       anObject->unselect();
1296   mySelectedObjects.clear();
1297 }
1298
1299 //================================================================
1300 // Function : setSelected
1301 // Purpose  : 
1302 //================================================================
1303 void GraphicsView_ViewPort::setSelected( GraphicsView_Object* theObject )
1304 {
1305   if( theObject )
1306   {
1307     theObject->setSelected( true );
1308     mySelectedObjects.append( theObject );
1309   }
1310 }
1311
1312 //================================================================
1313 // Function : nbSelected
1314 // Purpose  : 
1315 //================================================================
1316 int GraphicsView_ViewPort::nbSelected() const
1317 {
1318   return mySelectedObjects.count();
1319 }
1320
1321 //================================================================
1322 // Function : initSelected
1323 // Purpose  : 
1324 //================================================================
1325 void GraphicsView_ViewPort::initSelected()
1326 {
1327   mySelectionIterator = 0;
1328 }
1329
1330 //================================================================
1331 // Function : moreSelected
1332 // Purpose  : 
1333 //================================================================
1334 bool GraphicsView_ViewPort::moreSelected()
1335 {
1336   return mySelectionIterator < nbSelected();
1337 }
1338
1339 //================================================================
1340 // Function : nextSelected
1341 // Purpose  : 
1342 //================================================================
1343 bool GraphicsView_ViewPort::nextSelected()
1344 {
1345   if( mySelectionIterator >= 0 && mySelectionIterator < nbSelected() )
1346   {
1347     mySelectionIterator++;
1348     return true;
1349   }
1350   return false;
1351 }
1352
1353 //================================================================
1354 // Function : selectedObject
1355 // Purpose  : 
1356 //================================================================
1357 GraphicsView_Object* GraphicsView_ViewPort::selectedObject()
1358 {
1359   if( mySelectionIterator >= 0 && mySelectionIterator < nbSelected() )
1360     return mySelectedObjects[ mySelectionIterator ];
1361   return 0;
1362 }
1363
1364 //================================================================
1365 // Function : startSelectByRect
1366 // Purpose  : 
1367 //================================================================
1368 void GraphicsView_ViewPort::startSelectByRect( int x, int y )
1369 {
1370   if( !myAreSelectionPointsInitialized )
1371   {
1372     myFirstSelectionPoint = QPoint( x, y );
1373     myLastSelectionPoint = QPoint( x, y );
1374     myAreSelectionPointsInitialized = true;
1375   }
1376
1377   if( !myRectBand )
1378   {
1379     myRectBand = new QRubberBand( QRubberBand::Rectangle, this );
1380     QPalette palette;
1381     palette.setColor( myRectBand->foregroundRole(), Qt::white );
1382     myRectBand->setPalette( palette );
1383   }
1384   myRectBand->hide();
1385 }
1386
1387 //================================================================
1388 // Function : drawSelectByRect
1389 // Purpose  : 
1390 //================================================================
1391 void GraphicsView_ViewPort::drawSelectByRect( int x, int y )
1392 {
1393   if( myAreSelectionPointsInitialized )
1394   {
1395     myRectBand->hide();
1396
1397     myLastSelectionPoint.setX( x );
1398     myLastSelectionPoint.setY( y );
1399
1400     QRect aRect = selectionRect();
1401     myRectBand->setGeometry( aRect );
1402     myRectBand->setVisible( aRect.isValid() );
1403   }
1404 }
1405
1406 //================================================================
1407 // Function : isSelectByRect
1408 // Purpose  : 
1409 //================================================================
1410 bool GraphicsView_ViewPort::isSelectByRect() const
1411 {
1412   return myAreSelectionPointsInitialized;
1413 }
1414
1415 //================================================================
1416 // Function : finishSelectByRect
1417 // Purpose  : 
1418 //================================================================
1419 void GraphicsView_ViewPort::finishSelectByRect()
1420 {
1421   if( myAreSelectionPointsInitialized )
1422   {
1423     if( myRectBand )
1424     {
1425       myRectBand->hide();
1426       delete myRectBand;
1427       myRectBand = 0;
1428     }
1429
1430     myAreSelectionPointsInitialized = false;
1431   }
1432 }
1433
1434 //================================================================
1435 // Function : selectionRect
1436 // Purpose  : 
1437 //================================================================
1438 QRect GraphicsView_ViewPort::selectionRect()
1439 {
1440   QRect aRect;
1441   if( myAreSelectionPointsInitialized )
1442   {
1443     aRect.setLeft( qMin( myFirstSelectionPoint.x(), myLastSelectionPoint.x() ) );
1444     aRect.setTop( qMin( myFirstSelectionPoint.y(), myLastSelectionPoint.y() ) );
1445     aRect.setRight( qMax( myFirstSelectionPoint.x(), myLastSelectionPoint.x() ) );
1446     aRect.setBottom( qMax( myFirstSelectionPoint.y(), myLastSelectionPoint.y() ) );
1447   }
1448   return aRect;
1449 }
1450
1451 //================================================================
1452 // Function : prepareToSketch
1453 // Purpose  : 
1454 //================================================================
1455 void GraphicsView_ViewPort::prepareToSketch( bool theStatus )
1456 {
1457   myIsPrepareToSketch = theStatus;
1458   if( theStatus )
1459     setCursor( *getSketchCursor() );
1460 }
1461
1462 //================================================================
1463 // Function : isPrepareToSketch
1464 // Purpose  : 
1465 //================================================================
1466 bool GraphicsView_ViewPort::isPrepareToSketch()
1467 {
1468   return myIsPrepareToSketch;
1469 }
1470
1471 //================================================================
1472 // Function : startSketching
1473 // Purpose  : 
1474 //================================================================
1475 void GraphicsView_ViewPort::startSketching( const QPointF& thePoint,
1476                                             bool theIsPath )
1477 {
1478   prepareToSketch( false );
1479
1480   if( !mySketchingItem )
1481   {
1482     mySketchingItem = new QGraphicsPathItem();
1483     mySketchingItem->setZValue( SKETCH_Z_VALUE );
1484
1485     QPen aPen = mySketchingItem->pen();
1486     aPen.setStyle( Qt::DotLine );
1487     mySketchingItem->setPen( aPen );
1488
1489     addItem( mySketchingItem );
1490   }
1491
1492   mySketchingPoint = thePoint;
1493
1494   QPainterPath aPath;
1495   aPath.moveTo( mySketchingPoint );
1496   mySketchingItem->setPath( aPath );
1497   mySketchingItem->setVisible( true );
1498
1499   myIsSketching = true;
1500   myIsSketchingByPath = theIsPath;
1501 }
1502
1503 //================================================================
1504 // Function : drawSketching
1505 // Purpose  : 
1506 //================================================================
1507 void GraphicsView_ViewPort::drawSketching( const QPointF& thePoint )
1508 {
1509   bool anIsPath = false;
1510   if( mySketchingItem && isSketching( &anIsPath ) )
1511   {
1512     QPainterPath aPath = mySketchingItem->path();
1513     if( anIsPath ) // arbitrary path
1514       aPath.lineTo( thePoint );
1515     else // rectangle
1516     {
1517       // make a valid rectangle
1518       double x1 = mySketchingPoint.x(), y1 = mySketchingPoint.y();
1519       double x2 = thePoint.x(), y2 = thePoint.y();
1520       QPointF aPoint1( qMin( x1, x2 ), qMin( y1, y2 ) );
1521       QPointF aPoint2( qMax( x1, x2 ), qMax( y1, y2 ) );
1522       QRectF aRect( aPoint1, aPoint2 );
1523
1524       aPath = QPainterPath();
1525       aPath.addRect( aRect );
1526     }
1527     mySketchingItem->setPath( aPath );
1528   }
1529 }
1530
1531 //================================================================
1532 // Function : finishSketching
1533 // Purpose  : 
1534 //================================================================
1535 void GraphicsView_ViewPort::finishSketching( bool theStatus )
1536 {
1537   prepareToSketch( false );
1538
1539   mySketchingItem->setVisible( false );
1540   myIsSketching = false;
1541
1542   setCursor( *getDefaultCursor() );
1543
1544   if( theStatus )
1545   {
1546     QPainterPath aPath = mySketchingItem->path();
1547     emit vpSketchingFinished( aPath );
1548   }
1549 }
1550
1551 //================================================================
1552 // Function : isSketching
1553 // Purpose  : 
1554 //================================================================
1555 bool GraphicsView_ViewPort::isSketching( bool* theIsPath ) const
1556 {
1557   if( theIsPath )
1558     *theIsPath = myIsSketchingByPath;
1559   return myIsSketching;
1560 }
1561
1562 //================================================================
1563 // Function : setDraggingSelectedByLeftButton
1564 // Purpose  : 
1565 //================================================================
1566 void GraphicsView_ViewPort::setDraggingSelectedByLeftButton( const bool& theValue )
1567 {
1568   myDraggingSelectedByLeftButton = theValue;
1569 }
1570
1571 //================================================================
1572 // Function : dragObjects
1573 // Purpose  : 
1574 //================================================================
1575 void GraphicsView_ViewPort::dragObjects( QGraphicsSceneMouseEvent* e )
1576 {
1577   GraphicsView_Object* anObject = getHighlightedObject();
1578
1579   if( myDragPosition.isNull() )
1580   {
1581     myDragPosition = e->scenePos();
1582     return;
1583   }
1584
1585   GraphicsView_ObjectList anObjectsToMove;
1586   if( anObject && anObject->isMovable() && ( e->buttons() & Qt::LeftButton ) )
1587   {
1588     if( anObject->isSelected() )
1589     {
1590       for( initSelected(); moreSelected(); nextSelected() )
1591         if( GraphicsView_Object* aMovingObject = selectedObject() )
1592           if( aMovingObject->isMovable() )
1593             anObjectsToMove.append( aMovingObject );
1594     }
1595     else
1596       anObjectsToMove.append( anObject );
1597   }
1598   else if( ( hasInteractionFlag( DraggingByMiddleButton ) && ( e->buttons() & Qt::MidButton ) ||
1599              isDraggingSelectedByLeftButton() && ( e->buttons() & Qt::LeftButton ) ) &&
1600            nbSelected() )
1601   {
1602     for( initSelected(); moreSelected(); nextSelected() )
1603       if( GraphicsView_Object* aMovingObject = selectedObject() )
1604         if( aMovingObject->isMovable() )
1605           anObjectsToMove.append( aMovingObject );
1606   }
1607
1608   if( anObjectsToMove.isEmpty() )
1609     return;
1610
1611   double aDX = e->scenePos().x() - myDragPosition.x();
1612   double aDY = e->scenePos().y() - myDragPosition.y();
1613
1614   bool anIsMovingByXAllowed = true, anIsMovingByYAllowed = true;
1615   GraphicsView_ObjectListIterator anIter( anObjectsToMove );
1616   while( anIter.hasNext() )
1617     if( GraphicsView_Object* aMovingObject = anIter.next() )
1618     {
1619       if( !aMovingObject->isMovingByXAllowed( aDX ) )
1620         anIsMovingByXAllowed = false;
1621       if( !aMovingObject->isMovingByYAllowed( aDY ) )
1622         anIsMovingByYAllowed = false;
1623     }
1624
1625   if( !anIsMovingByXAllowed && !anIsMovingByYAllowed )
1626     return; // myDragPosition shouldn't be changed
1627
1628   if( !anIsMovingByXAllowed )
1629     aDX = 0;
1630
1631   if( !anIsMovingByYAllowed )
1632     aDY = 0;
1633
1634   anIter = anObjectsToMove;
1635   while( anIter.hasNext() )
1636     if( GraphicsView_Object* aMovingObject = anIter.next() )
1637       aMovingObject->move( aDX, aDY );
1638
1639   if( anIsMovingByXAllowed )
1640     myDragPosition.setX( e->scenePos().x() );
1641
1642   if( anIsMovingByYAllowed )
1643     myDragPosition.setY( e->scenePos().y() );
1644 }
1645
1646 //================================================================
1647 // Function : startPulling
1648 // Purpose  : 
1649 //================================================================
1650 bool GraphicsView_ViewPort::startPulling( const QPointF& thePoint )
1651 {
1652   QListIterator<QGraphicsItem*> anIter( items() );
1653   while( anIter.hasNext() )
1654   {
1655     if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1656     {
1657       QRectF aRect = anObject->getPullingRect();
1658       if( aRect.contains( thePoint ) && anObject->startPulling( thePoint ) )
1659       {
1660         myIsPulling = true;
1661         myPullingObject = anObject;
1662         //setCursor( *getHandCursor() ); // testing ImageViewer
1663         return true;
1664       }
1665     }
1666   }
1667   return false;
1668 }
1669
1670 //================================================================
1671 // Function : drawPulling
1672 // Purpose  : 
1673 //================================================================
1674 void GraphicsView_ViewPort::drawPulling( const QPointF& thePoint )
1675 {
1676   GraphicsView_Object* aLockedObject = 0;
1677
1678   QListIterator<QGraphicsItem*> anIter( items() );
1679   while( anIter.hasNext() )
1680   {
1681     if( GraphicsView_Object* anObject = dynamic_cast<GraphicsView_Object*>( anIter.next() ) )
1682     {
1683       if( !anObject->isVisible() )
1684         continue;
1685
1686       QRectF aRect = anObject->getPullingRect();
1687       if( aRect.contains( thePoint ) && anObject->portContains( thePoint ) )
1688       {
1689         aLockedObject = anObject;
1690         break;
1691       }
1692     }
1693   }
1694
1695   myPullingObject->pull( thePoint, aLockedObject, getSelectedObjects() );
1696 }
1697
1698 //================================================================
1699 // Function : finishPulling
1700 // Purpose  : 
1701 //================================================================
1702 void GraphicsView_ViewPort::finishPulling( bool theStatus )
1703 {
1704   myIsPulling = false;
1705   myPullingObject->finishPulling( theStatus, getSelectedObjects() );
1706   setCursor( *getDefaultCursor() );
1707 }
1708
1709 //================================================================
1710 // Function : cancelCurrentOperation
1711 // Purpose  : 
1712 //================================================================
1713 bool GraphicsView_ViewPort::cancelCurrentOperation()
1714 {
1715   myIsHighlighting = false;
1716
1717   if( isDragging() )
1718   {
1719     for( initSelected(); moreSelected(); nextSelected() )
1720       if( GraphicsView_Object* aMovingObject = selectedObject() )
1721         aMovingObject->finishMove( false );
1722
1723     if( GraphicsView_Object* aMovingObject = getHighlightedObject() )
1724       aMovingObject->finishMove( false );
1725
1726     myIsDragging = false;
1727     myDragPosition = QPointF();
1728     //setCursor( myStoredCursor );
1729     setCursor( *getDefaultCursor() );
1730
1731     return true;
1732   }
1733
1734   if( isPulling() )
1735   {
1736     finishPulling( false );
1737     return true;
1738   }
1739
1740   if( isSketching() || isPrepareToSketch() )
1741   {
1742     finishSketching( false );
1743     return true;
1744   }
1745
1746   return false;
1747 }
1748
1749 //================================================================
1750 // Function : onBoundingRectChanged
1751 // Purpose  : 
1752 //================================================================
1753 void GraphicsView_ViewPort::onBoundingRectChanged()
1754 {
1755   if( hasInteractionFlag( TraceBoundingRect ) )
1756   {
1757     QRectF aRect = objectsBoundingRect( true );
1758     myScene->setSceneRect( aRect.adjusted( -mySceneGap, -mySceneGap, mySceneGap, mySceneGap ) );
1759   }
1760 }
1761
1762 //================================================================
1763 // Function : onKeyEvent
1764 // Purpose  : 
1765 //================================================================
1766 void GraphicsView_ViewPort::onKeyEvent( QKeyEvent* e )
1767 {
1768   emit vpKeyEvent( e );
1769 }
1770
1771 //================================================================
1772 // Function : onMouseEvent
1773 // Purpose  : 
1774 //================================================================
1775 void GraphicsView_ViewPort::onMouseEvent( QGraphicsSceneMouseEvent* e )
1776 {
1777   emit vpMouseEvent( e );
1778
1779   bool anIsHandled = false;
1780   switch( e->type() )
1781   {
1782     case QEvent::GraphicsSceneMousePress:
1783     {
1784       if( hasInteractionFlag( EditFlags ) && nbSelected() )
1785         for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1786           if( GraphicsView_Object* anObject = selectedObject() )
1787             anIsHandled = anObject->handleMousePress( e );
1788
1789       if( !anIsHandled && hasInteractionFlag( Dragging ) )
1790       {
1791         bool anAccel = e->modifiers() & GraphicsView_ViewTransformer::accelKey();
1792         if( ( getHighlightedObject() &&
1793               getHighlightedObject()->isMovable() &&
1794               !( anAccel || e->button() != Qt::LeftButton ) ) ||
1795             ( ( hasInteractionFlag( DraggingByMiddleButton ) && e->button() == Qt::MidButton ||
1796                 isDraggingSelectedByLeftButton() && e->button() == Qt::LeftButton ) &&
1797               nbSelected() && !anAccel ) )
1798         {
1799           myIsDragging = true;
1800           myStoredCursor = cursor();
1801           setCursor( Qt::ClosedHandCursor );
1802         }
1803       }
1804       break;
1805     }
1806     case QEvent::GraphicsSceneMouseMove:
1807     {
1808       if( hasInteractionFlag( EditFlags ) && nbSelected() )
1809         for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1810           if( GraphicsView_Object* anObject = selectedObject() )
1811             anIsHandled = anObject->handleMouseMove( e );
1812
1813       if( !anIsHandled && !isPulling() && myIsDragging )
1814         dragObjects( e );
1815       break;
1816     }
1817     case QEvent::GraphicsSceneMouseRelease:
1818     {
1819       if( hasInteractionFlag( EditFlags ) && nbSelected() )
1820         for( initSelected(); moreSelected() && !anIsHandled; nextSelected() )
1821           if( GraphicsView_Object* anObject = selectedObject() )
1822             anIsHandled = anObject->handleMouseRelease( e );
1823
1824       if( !anIsHandled && !isPulling() && myIsDragging )
1825       {
1826         emit vpObjectBeforeMoving();
1827
1828         bool anIsMoved = false;
1829         for( initSelected(); moreSelected(); nextSelected() )
1830           if( GraphicsView_Object* aMovingObject = selectedObject() )
1831             anIsMoved = aMovingObject->finishMove( true ) || anIsMoved;
1832
1833         if( GraphicsView_Object* aMovingObject = getHighlightedObject() )
1834           anIsMoved = aMovingObject->finishMove( true ) || anIsMoved;
1835
1836         myIsDragging = false;
1837         myDragPosition = QPointF();
1838         setCursor( myStoredCursor );
1839
1840         emit vpObjectAfterMoving( anIsMoved );
1841       }
1842       break;
1843     }
1844     case QEvent::GraphicsSceneMouseDoubleClick:
1845       break; // do nothing, just emit the signal
1846     default:
1847       break;
1848   }
1849
1850   if( myIsMousePositionEnabled )
1851   {
1852     int aMouseX = (int)e->scenePos().x();
1853     int aMouseY = (int)e->scenePos().y();
1854     setViewLabelText( QString( "(%1, %2)" ).arg( aMouseX ).arg( aMouseY ) );
1855   }
1856 }
1857
1858 //================================================================
1859 // Function : onWheelEvent
1860 // Purpose  : 
1861 //================================================================
1862 void GraphicsView_ViewPort::onWheelEvent( QGraphicsSceneWheelEvent* e )
1863 {
1864   emit vpWheelEvent( e );
1865 }
1866
1867 //================================================================
1868 // Function : onContextMenuEvent
1869 // Purpose  : 
1870 //================================================================
1871 void GraphicsView_ViewPort::onContextMenuEvent( QGraphicsSceneContextMenuEvent* e )
1872 {
1873   emit vpContextMenuEvent( e );
1874 }
1875
1876 //================================================================
1877 // Function : scrollContentsBy
1878 // Purpose  : 
1879 //================================================================
1880 void GraphicsView_ViewPort::scrollContentsBy( int theDX, int theDY )
1881 {
1882   if( myViewLabel )
1883     myViewLabel->setAcceptMoveEvents( false );
1884
1885   QGraphicsView::scrollContentsBy( theDX, theDY );
1886
1887   if( myViewLabel )
1888     myViewLabel->setAcceptMoveEvents( true );
1889 }