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