Salome HOME
#refs 76 - reported by Hervé Legrand: Edit Sketch as Constructions child - crash
[modules/shaper.git] / src / XGUI / XGUI_ViewWindow.cpp
1 #include "XGUI_ViewWindow.h"
2 #include "XGUI_ViewPort.h"
3 #include "XGUI_Viewer.h"
4 #include "XGUI_Tools.h"
5 #include "XGUI_RubberBand.h"
6
7 #include <QLayout>
8 #include <QLabel>
9 #include <QToolBar>
10 #include <QAction>
11 #include <QResizeEvent>
12 #include <QApplication>
13 #include <QMdiArea>
14 #include <QMdiSubWindow>
15 #include <QPainter>
16 #include <QTimer>
17 #include <QFileDialog>
18 #include <QStyleOptionToolBar>
19
20 #include <TopoDS_Shape.hxx>
21 #include <BRep_Tool.hxx>
22 #include <TopoDS.hxx>
23 #include <Visual3d_View.hxx>
24
25 #define BORDER_SIZE 2
26
27 const char* imageZoomCursor[] = { "32 32 3 1", ". c None", "a c #000000", "# c #ffffff",
28     "................................", "................................",
29     ".#######........................", "..aaaaaaa.......................",
30     "................................", ".............#####..............",
31     "...........##.aaaa##............", "..........#.aa.....a#...........",
32     ".........#.a.........#..........", ".........#a..........#a.........",
33     "........#.a...........#.........", "........#a............#a........",
34     "........#a............#a........", "........#a............#a........",
35     "........#a............#a........", ".........#...........#.a........",
36     ".........#a..........#a.........", ".........##.........#.a.........",
37     "........#####.....##.a..........", ".......###aaa#####.aa...........",
38     "......###aa...aaaaa.......#.....", ".....###aa................#a....",
39     "....###aa.................#a....", "...###aa...............#######..",
40     "....#aa.................aa#aaaa.", ".....a....................#a....",
41     "..........................#a....", "...........................a....",
42     "................................", "................................",
43     "................................", "................................" };
44
45 const char* imageRotateCursor[] = { "32 32 3 1", ". c None", "a c #000000", "# c #ffffff",
46     "................................", "................................",
47     "................................", "................................",
48     "........#.......................", ".......#.a......................",
49     "......#######...................", ".......#aaaaa#####..............",
50     "........#..##.a#aa##........##..", ".........a#.aa..#..a#.....##.aa.",
51     ".........#.a.....#...#..##.aa...", ".........#a.......#..###.aa.....",
52     "........#.a.......#a..#aa.......", "........#a.........#..#a........",
53     "........#a.........#a.#a........", "........#a.........#a.#a........",
54     "........#a.........#a.#a........", ".........#.........#a#.a........",
55     "........##a........#a#a.........", "......##.a#.......#.#.a.........",
56     "....##.aa..##.....##.a..........", "..##.aa.....a#####.aa...........",
57     "...aa.........aaa#a.............", "................#.a.............",
58     "...............#.a..............", "..............#.a...............",
59     "...............a................", "................................",
60     "................................", "................................",
61     "................................", "................................" };
62
63 const char* imageCrossCursor[] = { "32 32 3 1", ". c None", "a c #000000", "# c #ffffff",
64     "................................", "................................",
65     "................................", "................................",
66     "................................", "................................",
67     "................................", "...............#................",
68     "...............#a...............", "...............#a...............",
69     "...............#a...............", "...............#a...............",
70     "...............#a...............", "...............#a...............",
71     "...............#a...............", ".......#################........",
72     "........aaaaaaa#aaaaaaaaa.......", "...............#a...............",
73     "...............#a...............", "...............#a...............",
74     "...............#a...............", "...............#a...............",
75     "...............#a...............", "...............#a...............",
76     "................a...............", "................................",
77     "................................", "................................",
78     "................................", "................................",
79     "................................", "................................" };
80
81
82 ViewerToolbar::ViewerToolbar(QWidget* theParent, XGUI_ViewPort* thePort)
83   : QToolBar(theParent), myVPort(thePort), myResize(false)
84 {
85   connect(myVPort, SIGNAL(resized()), this, SLOT(onViewPortResized()));
86 }
87
88 void ViewerToolbar::paintEvent(QPaintEvent* theEvent)
89 {
90   //QToolBar::paintEvent(theEvent);
91   // Paint background
92   QPainter aPainter(this);
93   QRect aRect = rect();
94   QRect aVPRect = myVPort->rect();
95   QPoint aGlobPnt = mapToGlobal(aRect.topLeft());
96   QPoint aPnt = myVPort->mapFromGlobal(aGlobPnt);
97
98   QRect aImgRect(QRect(aPnt.x(), aPnt.y() + aVPRect.height() - aRect.height(),
99                        aRect.width(), aRect.height()));
100   QImage aImg = myVPort->dumpView(aImgRect, myResize);
101   if (!aImg.isNull())
102     aPainter.drawImage(aRect, aImg);
103   myResize = false;
104
105   // Paint foreground
106   QStyle *style = this->style();
107   QStyleOptionToolBar aOpt;
108   initStyleOption(&aOpt);
109
110   aOpt.rect = style->subElementRect(QStyle::SE_ToolBarHandle, &aOpt, this);
111   if (aOpt.rect.isValid())
112     style->drawPrimitive(QStyle::PE_IndicatorToolBarHandle, &aOpt, &aPainter, this);
113 }
114
115
116
117 //**************************************************************************
118 ViewerLabel::ViewerLabel(QWidget* theParent, XGUI_ViewPort* thePort)
119   : QLabel(theParent), myVPort(thePort), myResize(false)
120 {
121   connect(myVPort, SIGNAL(resized()), this, SLOT(onViewPortResized()));
122 }
123
124 void ViewerLabel::paintEvent(QPaintEvent* theEvent)
125 {
126   QRect aRect = rect();
127   QRect aVPRect = myVPort->rect();
128   QPoint aGlobPnt = mapToGlobal(aRect.topLeft());
129   QPoint aPnt = myVPort->mapFromGlobal(aGlobPnt);
130
131   QRect aImgRect(QRect(aPnt.x(), aPnt.y() + aVPRect.height() - aRect.height(), 
132                  aRect.width(), aRect.height()));
133   QImage aImg = myVPort->dumpView(aImgRect, myResize);
134   if (!aImg.isNull())
135     QPainter(this).drawImage(aRect, aImg);
136   myResize = false;
137   QLabel::paintEvent(theEvent);
138 }
139
140 //**************************************************************************
141 //**************************************************************************
142 //**************************************************************************
143 XGUI_ViewWindow::XGUI_ViewWindow(XGUI_Viewer* theViewer, V3d_TypeOfView theType)
144     : QFrame(), 
145     myViewer(theViewer), 
146     myMoving(false), 
147     MinimizeIco(":pictures/wnd_minimize.png"), 
148     MaximizeIco(":pictures/wnd_maximize.png"), 
149     CloseIco(":pictures/wnd_close.png"), 
150     RestoreIco(":pictures/wnd_restore.png"), 
151     myInteractionStyle(XGUI::STANDARD), 
152     myRectBand(0), 
153     myIsKeyFree(false), 
154     my2dMode(XGUI::No2dMode), 
155     myCurrPointType(XGUI::GRAVITY), 
156     myPrevPointType(XGUI::GRAVITY), 
157     myRotationPointSelection(false),
158     myClosable(true),
159     myStartX(0), myStartY(0), myCurrX(0), myCurrY(0), myCurScale(0.0), myCurSketch(0),
160     myDrawRect(false), myEnableDrawMode(false), myCursorIsHand(false), myEventStarted(false),
161     myIsActive(false),
162     myLastState(WindowNormalState), myOperation(NOTHING)
163 {
164   mySelectedPoint = gp_Pnt(0., 0., 0.);
165   setFrameStyle(QFrame::Raised);
166   setFrameShape(QFrame::Panel);
167   setLineWidth(BORDER_SIZE);
168   setMouseTracking(true);
169
170   QVBoxLayout* aLay = new QVBoxLayout(this);
171   aLay->setContentsMargins(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE);
172   myViewPort = new XGUI_ViewPort(this, myViewer->v3dViewer(), theType);
173   myViewPort->installEventFilter(this);
174   myViewPort->setCursor(Qt::ArrowCursor);
175   aLay->addWidget(myViewPort);
176
177   myPicture = new QLabel(this);
178   myPicture->setFrameStyle(QFrame::Sunken);
179   myPicture->setFrameShape(QFrame::Panel);
180   myPicture->setMouseTracking(true);
181   myPicture->installEventFilter(this);
182   aLay->addWidget(myPicture);
183   myPicture->hide();
184
185   QVBoxLayout* aVPLay = new QVBoxLayout(myViewPort);
186   aVPLay->setMargin(0);
187   aVPLay->setSpacing(0);
188   aVPLay->setContentsMargins(0,0,0,0);
189
190   QHBoxLayout* aToolLay = new QHBoxLayout();
191   aToolLay->setMargin(0);
192   aToolLay->setSpacing(0);
193   aToolLay->setContentsMargins(0,0,0,0);
194   aVPLay->addLayout(aToolLay);
195   aVPLay->addStretch(); 
196
197   myGripWgt = new ViewerLabel(this, myViewPort);
198   myGripWgt->setPixmap(QPixmap(":pictures/wnd_grip.png"));
199   myGripWgt->setMouseTracking(true);
200   myGripWgt->installEventFilter(this);
201   myGripWgt->setCursor(Qt::OpenHandCursor);
202   aToolLay->addWidget(myGripWgt);
203
204     // Create Viewer management buttons
205   myViewBar = new ViewerToolbar(this, myViewPort);
206   myViewBar->setCursor(Qt::PointingHandCursor);
207   aToolLay->addWidget(myViewBar); 
208   aToolLay->addStretch();
209
210   QAction* aBtn;
211
212   // Dump view
213   aBtn = new QAction(QIcon(":pictures/occ_view_camera_dump.png"), tr("Dump view"), myViewBar);
214   connect(aBtn, SIGNAL(triggered()), SLOT(dumpView()));
215   myViewBar->addAction(aBtn);
216   // Fit all
217   aBtn = new QAction(QIcon(":pictures/occ_view_fitall.png"), tr("Fit all"), myViewBar);
218   connect(aBtn, SIGNAL(triggered()), SLOT(fitAll()));
219   myViewBar->addAction(aBtn);
220   // Fit area
221   aBtn = new QAction(QIcon(":pictures/occ_view_fitarea.png"), tr("Fit area"), myViewBar);
222   connect(aBtn, SIGNAL(triggered()), SLOT(activateWindowFit()));
223   myViewBar->addAction(aBtn);
224   // Zoom
225   aBtn = new QAction(QIcon(":pictures/occ_view_zoom.png"), tr("Zoom"), myViewBar);
226   connect(aBtn, SIGNAL(triggered()), SLOT(activateZoom()));
227   myViewBar->addAction(aBtn);
228   // Pan
229   aBtn = new QAction(QIcon(":pictures/occ_view_pan.png"), tr("Panning"), myViewBar);
230   connect(aBtn, SIGNAL(triggered()), SLOT(activatePanning()));
231   myViewBar->addAction(aBtn);
232   // Global Panning
233   aBtn = new QAction(QIcon(":pictures/occ_view_glpan.png"), tr("Global panning"), myViewBar);
234   connect(aBtn, SIGNAL(triggered()), SLOT(activateGlobalPanning()));
235   myViewBar->addAction(aBtn);
236   // Rotation
237   aBtn = new QAction(QIcon(":pictures/occ_view_rotate.png"), tr("Rotate"), myViewBar);
238   connect(aBtn, SIGNAL(triggered()), SLOT(activateRotation()));
239   myViewBar->addAction(aBtn);
240   // Reset
241   aBtn = new QAction(QIcon(":pictures/occ_view_reset.png"), tr("Reset"), myViewBar);
242   connect(aBtn, SIGNAL(triggered()), SLOT(reset()));
243   myViewBar->addAction(aBtn);
244   // Front view
245   aBtn = new QAction(QIcon(":pictures/occ_view_front.png"), tr("Front"), myViewBar);
246   connect(aBtn, SIGNAL(triggered()), SLOT(frontView()));
247   myViewBar->addAction(aBtn);
248   // Back view
249   aBtn = new QAction(QIcon(":pictures/occ_view_back.png"), tr("Back"), myViewBar);
250   connect(aBtn, SIGNAL(triggered()), SLOT(backView()));
251   myViewBar->addAction(aBtn);
252   // Top view
253   aBtn = new QAction(QIcon(":pictures/occ_view_top.png"), tr("Top"), myViewBar);
254   connect(aBtn, SIGNAL(triggered()), SLOT(topView()));
255   myViewBar->addAction(aBtn);
256   // Bottom view
257   aBtn = new QAction(QIcon(":pictures/occ_view_bottom.png"), tr("Bottom"), myViewBar);
258   connect(aBtn, SIGNAL(triggered()), SLOT(bottomView()));
259   myViewBar->addAction(aBtn);
260   // Left view
261   aBtn = new QAction(QIcon(":pictures/occ_view_left.png"), tr("Left"), myViewBar);
262   connect(aBtn, SIGNAL(triggered()), SLOT(leftView()));
263   myViewBar->addAction(aBtn);
264   // Right view
265   aBtn = new QAction(QIcon(":pictures/occ_view_right.png"), tr("Right"), myViewBar);
266   connect(aBtn, SIGNAL(triggered()), SLOT(rightView()));
267   myViewBar->addAction(aBtn);
268   // Clone view
269   aBtn = new QAction(QIcon(":pictures/occ_view_clone.png"), tr("Clone"), myViewBar);
270   connect(aBtn, SIGNAL(triggered()), SLOT(cloneView()));
271   myViewBar->addAction(aBtn);
272
273     // Create Window management buttons
274   myWindowBar = new ViewerToolbar(this, myViewPort);
275   myWindowBar->setCursor(Qt::PointingHandCursor);
276   aToolLay->addWidget(myWindowBar);
277
278   myMinimizeBtn = new QAction(myWindowBar);
279   myMinimizeBtn->setIcon(MinimizeIco);
280   myWindowBar->addAction(myMinimizeBtn);
281   connect(myMinimizeBtn, SIGNAL(triggered()), SLOT(onMinimize()));
282
283   myMaximizeBtn = new QAction(myWindowBar);
284   myMaximizeBtn->setIcon(MaximizeIco);
285   myWindowBar->addAction(myMaximizeBtn);
286   connect(myMaximizeBtn, SIGNAL(triggered()), SLOT(onMaximize()));
287
288   aBtn = new QAction(myWindowBar);
289   aBtn->setIcon(CloseIco);
290   myWindowBar->addAction(aBtn);
291   connect(aBtn, SIGNAL(triggered()), SLOT(onClose()));
292
293   //Support copy of background on updating of viewer
294   connect(myViewPort, SIGNAL(vpTransformed()), this, SLOT(updateToolBar()));
295   connect(myViewPort, SIGNAL(vpUpdated()), this, SLOT(updateToolBar()));
296   connect(this, SIGNAL(vpTransformationFinished(XGUI_ViewWindow::OperationType)), 
297           this, SLOT(updateToolBar()));
298 }
299
300 //****************************************************************
301 XGUI_ViewWindow::~XGUI_ViewWindow()
302 {
303 }
304
305
306 //****************************************************************
307 void XGUI_ViewWindow::showEvent(QShowEvent* theEvent)
308 {
309   QFrame::showEvent(theEvent);
310   myWindowBar->setFixedSize(myWindowBar->sizeHint());
311 }
312
313 //****************************************************************
314 void XGUI_ViewWindow::changeEvent(QEvent* theEvent)
315 {
316
317   if (theEvent->type() == QEvent::WindowStateChange) {
318     if (isMinimized()) {
319       if (myPicture->isHidden()) {
320         myViewBar->hide();
321         myGripWgt->hide(); 
322         myWindowBar->hide();
323         myViewPort->hide();
324         myPicture->show();
325       }
326     } else {
327       if (myPicture->isVisible()) {
328         myPicture->hide();
329         myViewPort->show();
330       }
331       if (isMaximized()) {
332         myMinimizeBtn->setIcon(MinimizeIco);
333         myMaximizeBtn->setIcon(RestoreIco);
334       }
335       myViewBar->setVisible(myIsActive);
336       myWindowBar->setVisible(myIsActive);
337       myGripWgt->setVisible(myIsActive && (!isMaximized()));
338     }
339   } else
340     QWidget::changeEvent(theEvent);
341 }
342
343
344
345 //****************************************************************
346 void XGUI_ViewWindow::windowActivated()
347 {
348   if (!(isMinimized() || parentWidget()->isMinimized())) {
349     myIsActive = true;
350     if (isMaximized() || parentWidget()->isMaximized()) {
351       myMaximizeBtn->setIcon(RestoreIco);
352     } else {
353       myMaximizeBtn->setIcon(MaximizeIco);
354     }
355     myViewBar->show();
356     myWindowBar->show();
357     myGripWgt->setVisible(!(isMaximized() || isMinimized() ||
358         parentWidget()->isMaximized() || parentWidget()->isMinimized()));
359   } else 
360     myIsActive = false;
361 }
362
363 //****************************************************************
364 void XGUI_ViewWindow::windowDeactivated()
365 {
366   myIsActive = false;
367   if (!(isMinimized() || parentWidget()->isMinimized())) {
368     if (isMaximized() || parentWidget()->isMaximized()) {
369       myMaximizeBtn->setIcon(RestoreIco);
370     } else {
371       myMaximizeBtn->setIcon(MaximizeIco);
372     }
373     myViewBar->hide();
374     myWindowBar->hide();
375     myGripWgt->hide(); 
376   }
377 }
378
379
380 //****************************************************************
381 void XGUI_ViewWindow::onClose()
382 {
383   if (parentWidget()) {
384     emit tryClosing(this);
385     if (closable()) {
386       emit closed(static_cast<QMdiSubWindow*>(parentWidget()));
387       parentWidget()->close();
388     }
389   }
390 }
391
392 //****************************************************************
393 void XGUI_ViewWindow::onMinimize()
394 {
395   QPixmap aPMap = QPixmap::fromImage(myViewPort->dumpView());
396   int aW = width();
397   int aH = height();
398   double aR = aW / 100.;
399   int aNewH = int(aH / aR);
400   myPicture->setPixmap(aPMap.scaled(100,  aNewH));
401
402   myLastState = (isMaximized() || parentWidget()->isMaximized()) ? MaximizedState : WindowNormalState;
403   showMinimized();
404   parentWidget()->showMinimized();
405   parentWidget()->setGeometry(parentWidget()->x(), parentWidget()->y(), 100, aNewH);
406   parentWidget()->lower();
407   windowDeactivated();
408   myViewer->onWindowMinimized((QMdiSubWindow*)parentWidget());
409 }
410
411 //****************************************************************
412 void XGUI_ViewWindow::onMaximize()
413 {
414   if (isMaximized() || parentWidget()->isMaximized()) {
415     myMaximizeBtn->setIcon(MaximizeIco);
416     myGripWgt->show();
417     showNormal();
418     parentWidget()->showNormal();
419   } else {
420     myMaximizeBtn->setIcon(RestoreIco);
421     myGripWgt->hide();
422     showMaximized();
423     parentWidget()->showMaximized();
424   }
425   parentWidget()->activateWindow();
426   myMinimizeBtn->setIcon(MinimizeIco);
427   
428   //  In order to avoid frosen background in toolbars when it shown as a second view
429   QTimer::singleShot(50, parentWidget(), SLOT(setFocus()));
430 }
431
432 //****************************************************************
433 bool XGUI_ViewWindow::processWindowControls(QObject *theObj, QEvent *theEvent)
434 {
435   switch(theEvent->type()) {
436   case QEvent::MouseButtonPress: {
437     QMouseEvent* aEvent = static_cast<QMouseEvent*>(theEvent);
438     if ((aEvent->button() == Qt::LeftButton) && (!myMoving)) {
439       myMoving = true;
440       myMousePnt = aEvent->globalPos();
441       return true;
442     }
443   }
444     break;
445   case QEvent::MouseButtonRelease: {
446     QMouseEvent* aEvent = static_cast<QMouseEvent*>(theEvent);
447     if ((aEvent->button() == Qt::LeftButton) && myMoving) {
448       myMoving = false;
449       return true;
450     }
451   }
452     break;
453   case QEvent::MouseMove: {
454     QMouseEvent* aEvent = static_cast<QMouseEvent*>(theEvent);
455     if (myMoving) {
456       QMdiSubWindow* aParent = static_cast<QMdiSubWindow*>(parentWidget());
457       QMdiArea* aMDIArea = aParent->mdiArea();
458
459       QPoint aPnt = aEvent->globalPos();
460       QPoint aMDIPnt = aMDIArea->mapFromGlobal(aPnt);
461       if (aMDIArea->rect().contains(aMDIPnt)) {
462                     int aX = aParent->x() + (aPnt.x() - myMousePnt.x());
463                     int aY = aParent->y() + (aPnt.y() - myMousePnt.y());
464                     aParent->move(aX, aY);
465         myMousePnt = aPnt;
466       }
467       return true;
468     }
469   }
470     break;
471   case QEvent::MouseButtonDblClick:
472     if (theObj == myPicture) {
473       myMoving = false;
474       if (myLastState == MaximizedState) {
475         showMaximized();
476       } else {
477         showNormal();
478       }
479       myViewer->onWindowActivated((QMdiSubWindow*)parentWidget());
480
481       //  In order to avoid frosen background in toolbars when it shown as a second view
482       QTimer::singleShot(20, parentWidget(), SLOT(setFocus()));
483
484       return true;
485     }
486   }
487   return false;
488 }
489
490 //****************************************************************
491 bool XGUI_ViewWindow::processViewPort(QEvent *theEvent)
492 {
493   switch(theEvent->type()) {
494   case QEvent::MouseButtonPress:
495     vpMousePressEvent((QMouseEvent*) theEvent);
496     return true;
497
498   case QEvent::MouseButtonRelease:
499     vpMouseReleaseEvent((QMouseEvent*) theEvent);
500     return true;
501
502   case QEvent::MouseMove:
503     vpMouseMoveEvent((QMouseEvent*) theEvent);
504     return true;
505
506   case QEvent::MouseButtonDblClick:
507     emit mouseDoubleClicked(this, (QMouseEvent*) theEvent);
508     return true;
509     case QEvent::Wheel:
510         {
511             QWheelEvent* aEvent = (QWheelEvent*) theEvent;
512             myViewPort->startZoomAtPoint( aEvent->x(), aEvent->y() );
513             double aDelta = (double)( aEvent->delta() ) / ( 15 * 8 );
514             int x  = aEvent->x();
515             int y  = aEvent->y();
516             int x1 = (int)( aEvent->x() + width()*aDelta/100 );
517             int y1 = (int)( aEvent->y() + height()*aDelta/100 );
518             myViewPort->zoom( x, y, x1, y1 );
519         }
520         return true;
521   }
522   return false;
523 }
524
525 //****************************************************************
526 bool XGUI_ViewWindow::eventFilter(QObject *theObj, QEvent *theEvent)
527 {
528   if ((theObj == myGripWgt) || (theObj == myPicture)) {
529     if (processWindowControls(theObj, theEvent))
530       return true;
531   } else if (theObj == myViewPort) {
532     if (processViewPort(theEvent)) {
533       return true;
534     }
535     if (theEvent->type() == QEvent::KeyRelease) {
536       emit keyReleased(this, (QKeyEvent*) theEvent);
537       return true;
538     }
539   }
540   return QFrame::eventFilter(theObj, theEvent);
541 }
542
543 //****************************************************************
544 XGUI_ViewWindow::OperationType XGUI_ViewWindow::getButtonState(
545     QMouseEvent* theEvent, XGUI::InteractionStyle theInteractionStyle)
546 {
547   OperationType aOp = NOTHING;
548   XGUI::InteractionStyle aStyle = (XGUI::InteractionStyle) theInteractionStyle;
549   if ((theEvent->modifiers() == XGUI_Viewer::myStateMap[aStyle][XGUI::ZOOM])
550       && (theEvent->buttons() == XGUI_Viewer::myButtonMap[aStyle][XGUI::ZOOM]))
551     aOp = ZOOMVIEW;
552   else if ((theEvent->modifiers() == XGUI_Viewer::myStateMap[aStyle][XGUI::PAN])
553       && (theEvent->buttons() == XGUI_Viewer::myButtonMap[aStyle][XGUI::PAN]))
554     aOp = PANVIEW;
555   else if ((theEvent->modifiers() == XGUI_Viewer::myStateMap[aStyle][XGUI::ROTATE])
556       && (theEvent->buttons() == XGUI_Viewer::myButtonMap[aStyle][XGUI::ROTATE])
557       && (my2dMode == XGUI::No2dMode))
558     aOp = ROTATE;
559
560   return aOp;
561 }
562
563 //****************************************************************
564 void XGUI_ViewWindow::vpMousePressEvent(QMouseEvent* theEvent)
565 {
566   myStartX = theEvent->x();
567   myStartY = theEvent->y();
568   XGUI::InteractionStyle anInteractionStyle = interactionStyle();
569
570   // in "key free" interaction style zoom operation is activated by two buttons (simultaneously pressed),
571   // which are assigned for pan and rotate - these operations are activated immediately after pressing 
572   // of the first button, so it is necessary to switch to zoom when the second button is pressed
573   bool aSwitchToZoom = false;
574   if ((anInteractionStyle == XGUI::KEY_FREE) && (myOperation == PANVIEW || myOperation == ROTATE)) {
575     aSwitchToZoom = getButtonState(theEvent, anInteractionStyle) == ZOOMVIEW;
576   }
577
578   switch(myOperation) {
579   case WINDOWFIT:
580     if (theEvent->button() == Qt::LeftButton)
581       emit vpTransformationStarted(WINDOWFIT);
582     break;
583
584   case PANGLOBAL:
585     if (theEvent->button() == Qt::LeftButton)
586       emit vpTransformationStarted(PANGLOBAL);
587     break;
588
589   case ZOOMVIEW:
590     if (theEvent->button() == Qt::LeftButton) {
591       myViewPort->startZoomAtPoint(myStartX, myStartY);
592       emit vpTransformationStarted(ZOOMVIEW);
593     }
594     break;
595
596   case PANVIEW:
597     if (aSwitchToZoom) {
598       myViewPort->startZoomAtPoint(myStartX, myStartY);
599       activateZoom();
600     } else if (theEvent->button() == Qt::LeftButton)
601       emit vpTransformationStarted(PANVIEW);
602     break;
603
604   case ROTATE:
605     if (aSwitchToZoom) {
606       myViewPort->startZoomAtPoint(myStartX, myStartY);
607       activateZoom();
608     } else if (theEvent->button() == Qt::LeftButton) {
609       myViewPort->startRotation(myStartX, myStartY, myCurrPointType, mySelectedPoint);
610       emit vpTransformationStarted(ROTATE);
611     }
612     break;
613
614   default:
615     /*  Try to activate a transformation */
616     OperationType aState;
617     if (interactionStyle() == XGUI::STANDARD)
618       aState = getButtonState(theEvent, anInteractionStyle);
619     else {
620       aState = XGUI_ViewWindow::NOTHING;
621       myIsKeyFree = true;
622     }
623     switch(aState) {
624     case ZOOMVIEW:
625       myViewPort->startZoomAtPoint(myStartX, myStartY);
626       activateZoom();
627       break;
628     case PANVIEW:
629       activatePanning();
630       break;
631     case ROTATE:
632       activateRotation();
633       myViewPort->startRotation(myStartX, myStartY, myCurrPointType, mySelectedPoint);
634       break;
635     default:
636       if (myRotationPointSelection) {
637         if (theEvent->button() == Qt::LeftButton) {
638           Handle(AIS_InteractiveContext) ic = myViewer->AISContext();
639           ic->Select();
640           for(ic->InitSelected(); ic->MoreSelected(); ic->NextSelected()) {
641             TopoDS_Shape aShape = ic->SelectedShape();
642             if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX) {
643               gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(ic->SelectedShape()));
644               /*if ( mySetRotationPointDlg ) {
645                myRotationPointSelection = false;
646                mySetRotationPointDlg->setCoords(aPnt.X(), aPnt.Y(), aPnt.Z());
647                }*/
648             } else {
649               myCurrPointType = myPrevPointType;
650               break;
651             }
652           }
653           if (ic->NbSelected() == 0)
654             myCurrPointType = myPrevPointType;
655           //if ( mySetRotationPointDlg ) mySetRotationPointDlg->toggleChange();
656           ic->CloseAllContexts();
657           myOperation = NOTHING;
658           myViewPort->setCursor(myCursor);
659           myCursorIsHand = false;
660           myRotationPointSelection = false;
661         }
662       } else
663         emit mousePressed(this, theEvent);
664       break;
665     }
666     /* notify that we start a transformation */
667     if (transformRequested())
668       emit vpTransformationStarted(myOperation);
669   }
670   if (transformRequested())
671     setTransformInProcess(true);
672
673   /* we may need it for sketching... */
674   /*    if ( l_mbPressEvent )
675    delete l_mbPressEvent;
676    l_mbPressEvent = new QMouseEvent( *theEvent );*/
677 }
678
679 //****************************************************************
680 void XGUI_ViewWindow::contextMenuEvent(QContextMenuEvent* theEvent)
681 {
682   if (theEvent->modifiers() == Qt::NoModifier) {
683     // Temporary: has to be removed when viewer popup will be defined
684     //QFrame::contextMenuEvent(theEvent);
685     emit contextMenuRequested(theEvent);
686   }
687 }
688
689 //****************************************************************
690 void XGUI_ViewWindow::vpMouseReleaseEvent(QMouseEvent* theEvent)
691 {
692   switch(myOperation) {
693   case NOTHING: {
694     int prevState = myCurSketch;
695     /*            if(theEvent->button() == Qt::RightButton) {
696      QList<OCCViewer_ViewSketcher*>::Iterator it;
697      for ( it = mySketchers.begin(); it != mySketchers.end() && myCurSketch != -1; ++it ) {
698      OCCViewer_ViewSketcher* sk = (*it);
699      if( ( sk->sketchButton() & theEvent->button() ) && sk->sketchButton() == myCurSketch )
700      myCurSketch = -1;
701      }
702      }
703      */
704     emit mouseReleased(this, theEvent);
705   }
706     break;
707   case ROTATE:
708     myViewPort->endRotation();
709     resetState();
710     break;
711
712   case PANVIEW:
713   case ZOOMVIEW:
714     resetState();
715     break;
716
717   case PANGLOBAL:
718     if (theEvent->button() == Qt::LeftButton) {
719       myViewPort->setCenter(theEvent->x(), theEvent->y());
720       myViewPort->getView()->SetScale(myCurScale);
721       resetState();
722     }
723     break;
724
725   case WINDOWFIT:
726     if (theEvent->button() == Qt::LeftButton) {
727       myCurrX = theEvent->x();
728       myCurrY = theEvent->y();
729       drawRect();
730       QRect rect = XGUI_Tools::makeRect(myStartX, myStartY, myCurrX, myCurrY);
731       if (!rect.isEmpty())
732         myViewPort->fitRect(rect);
733       endDrawRect();
734       resetState();
735     }
736     break;
737   }
738
739   // NOTE: viewer 3D detects a rectangle of selection using this event
740   // so we must emit it BEFORE resetting the selection rectangle
741   if (theEvent->button() == Qt::LeftButton && myDrawRect) {
742     drawRect();
743     endDrawRect();
744     resetState();
745     myViewPort->update();
746   }
747   /*    if ( l_mbPressEvent ) {
748    delete l_mbPressEvent;
749    l_mbPressEvent = 0;
750    }*/
751 }
752
753 //****************************************************************
754 void XGUI_ViewWindow::vpMouseMoveEvent(QMouseEvent* theEvent)
755 {
756   if (myIsKeyFree && interactionStyle() == XGUI::KEY_FREE) {
757     myIsKeyFree = false;
758     switch(getButtonState(theEvent, interactionStyle())) {
759     case ZOOMVIEW:
760       myViewPort->startZoomAtPoint(myStartX, myStartY);
761       activateZoom();
762       break;
763     case PANVIEW:
764       activatePanning();
765       break;
766     case ROTATE:
767       activateRotation();
768       myViewPort->startRotation(myStartX, myStartY, myCurrPointType, mySelectedPoint);
769       break;
770     default:
771       break;
772     }
773   }
774
775   myCurrX = theEvent->x();
776   myCurrY = theEvent->y();
777   switch(myOperation) {
778   case ROTATE:
779     myViewPort->rotate(myCurrX, myCurrY, myCurrPointType, mySelectedPoint);
780     break;
781
782   case ZOOMVIEW:
783     myViewPort->zoom(myStartX, myStartY, myCurrX, myCurrY);
784     myStartX = myCurrX;
785     myStartY = myCurrY;
786     break;
787
788   case PANVIEW:
789     myViewPort->pan(myCurrX - myStartX, myStartY - myCurrY);
790     myStartX = myCurrX;
791     myStartY = myCurrY;
792     break;
793
794   case PANGLOBAL:
795     break;
796
797   default:
798     if (myRotationPointSelection /*|| isSketcherStyle()*/) {
799       emit mouseMoving(this, theEvent);
800     } else {
801       int aState = theEvent->modifiers();
802       int aButton = theEvent->buttons();
803       int anInteractionStyle = interactionStyle();
804       if (((anInteractionStyle == XGUI::STANDARD) && (aButton == Qt::LeftButton)
805           && (aState == Qt::NoModifier || Qt::ShiftModifier))
806           || ((anInteractionStyle == XGUI::KEY_FREE) && (aButton == Qt::LeftButton)
807               && (aState == Qt::ControlModifier
808                   || aState == (Qt::ControlModifier | Qt::ShiftModifier)))) {
809         myDrawRect = myEnableDrawMode;
810         if (myDrawRect) {
811           drawRect();
812           if (!myCursorIsHand) {   // we are going to sketch a rectangle
813             QCursor handCursor(Qt::PointingHandCursor);
814             myCursorIsHand = true;
815             myCursor = cursor();
816             myViewPort->setCursor(handCursor);
817           }
818         }
819         emit mouseMoving(this, theEvent);
820       } /* else if ( ( (anInteractionStyle == XGUI::STANDARD) &&
821        (aButton == Qt::RightButton) && 
822        ( aState == Qt::NoModifier || Qt::ShiftModifier ) ) ||
823        ( (anInteractionStyle == XGUI::KEY_FREE) &&
824        (aButton == Qt::RightButton) && 
825        ( aState == Qt::ControlModifier || aState == ( Qt::ControlModifier|Qt::ShiftModifier ) ) ) ) {
826        OCCViewer_ViewSketcher* sketcher = 0;
827        QList<OCCViewer_ViewSketcher*>::Iterator it;
828        for ( it = mySketchers.begin(); it != mySketchers.end() && !sketcher; ++it ) {
829        OCCViewer_ViewSketcher* sk = (*it);
830        if( sk->isDefault() && sk->sketchButton() == aButton )
831        sketcher = sk;
832        }
833        if ( sketcher && myCurSketch == -1 ) {
834        activateSketching( sketcher->type() );
835        if ( mypSketcher ) {
836        myCurSketch = mypSketcher->sketchButton();
837
838        if ( l_mbPressEvent )  {
839        QApplication::sendEvent( getViewPort(), l_mbPressEvent );
840        delete l_mbPressEvent;
841        l_mbPressEvent = 0;
842        }
843        QApplication::sendEvent( getViewPort(), theEvent );
844        }
845        }
846        } */else
847         emit mouseMoving(this, theEvent);
848     }
849   }
850 }
851
852 /*!
853  \brief Draw rubber band rectangle.
854  */
855 void XGUI_ViewWindow::drawRect()
856 {
857   if (!myRectBand) {
858     myRectBand = new XGUI_RectRubberBand(myViewPort);
859   }
860
861   myRectBand->setUpdatesEnabled(false);
862   QRect aRect = XGUI_Tools::makeRect(myStartX, myStartY, myCurrX, myCurrY);
863   myRectBand->initGeometry(aRect);
864
865   if (!myRectBand->isVisible())
866     myRectBand->show();
867
868   myRectBand->setUpdatesEnabled(true);
869 }
870
871 /*!
872  \brief Clear rubber band rectangle on the end on the dragging operation.
873  */
874 void XGUI_ViewWindow::endDrawRect()
875 {
876   if (myRectBand) {
877     myRectBand->clearGeometry();
878     myRectBand->hide();
879   }
880 }
881
882 void XGUI_ViewWindow::activateZoom()
883 {
884   if (!transformRequested() && !myCursorIsHand)
885     myCursor = cursor(); /* save old cursor */
886
887   if (myOperation != ZOOMVIEW) {
888     QPixmap zoomPixmap(imageZoomCursor);
889     QCursor zoomCursor(zoomPixmap);
890     if (setTransformRequested(ZOOMVIEW))
891       myViewPort->setCursor(zoomCursor);
892   }
893 }
894
895 bool XGUI_ViewWindow::transformRequested() const
896 {
897   return (myOperation != NOTHING);
898 }
899
900 /*!
901  \brief Start delayed viewer operation.
902  */
903 bool XGUI_ViewWindow::setTransformRequested(OperationType op)
904 {
905   bool ok = transformEnabled(op);
906   myOperation = ok ? op : NOTHING;
907   myViewPort->setMouseTracking(myOperation == NOTHING);
908   return ok;
909 }
910
911 /*!
912  Set enabled state of transformation (rotate, zoom, etc)
913  */
914 void XGUI_ViewWindow::setTransformEnabled(const OperationType id, const bool on)
915 {
916   if (id != NOTHING)
917     myStatus.insert(id, on);
918 }
919
920 /*!
921  \return enabled state of transformation (rotate, zoom, etc)
922  */
923 bool XGUI_ViewWindow::transformEnabled(const OperationType id) const
924 {
925   return myStatus.contains(id) ? myStatus[id] : true;
926 }
927
928 /*!
929  \brief Start panning operation.
930
931  Sets the corresponding cursor for the widget.
932  */
933 void XGUI_ViewWindow::activatePanning()
934 {
935   if (!transformRequested() && !myCursorIsHand)
936     myCursor = cursor();                // save old cursor
937
938   if (myOperation != PANVIEW) {
939     QCursor panCursor(Qt::SizeAllCursor);
940     if (setTransformRequested(PANVIEW))
941       myViewPort->setCursor(panCursor);
942   }
943 }
944
945 /*!
946   \brief Start global panning operation
947
948   Sets the corresponding cursor for the widget.
949 */
950 void XGUI_ViewWindow::activateGlobalPanning()
951 {
952   Handle(V3d_View) aView3d = myViewPort->getView();
953   if ( !aView3d.IsNull() ) {
954     QPixmap globalPanPixmap (imageCrossCursor);
955     QCursor glPanCursor (globalPanPixmap);
956     myCurScale = aView3d->Scale();
957     aView3d->FitAll(0.01, false);
958     myCursor = cursor();                // save old cursor
959     myViewPort->fitAll(); // fits view before selecting a new scene center
960     if( setTransformRequested( PANGLOBAL ) )
961       myViewPort->setCursor( glPanCursor );
962   }
963 }
964
965 /*!
966  \brief Start rotation operation
967
968  Sets the corresponding cursor for the widget.
969  */
970 void XGUI_ViewWindow::activateRotation()
971 {
972   if (!transformRequested() && !myCursorIsHand)
973     myCursor = cursor();                // save old cursor
974
975   if (myOperation != ROTATE) {
976     QPixmap rotatePixmap(imageRotateCursor);
977     QCursor rotCursor(rotatePixmap);
978     if (setTransformRequested(ROTATE))
979       myViewPort->setCursor(rotCursor);
980   }
981 }
982
983 /*!
984  \brief Reset the viewport to its initial state
985  ( no transformations in process etc. )
986  */
987 void XGUI_ViewWindow::resetState()
988 {
989   myDrawRect = false;
990
991   if (myRotationPointSelection) {
992     QCursor handCursor(Qt::PointingHandCursor);
993     myViewPort->setCursor(handCursor);
994   } else {
995     if (transformRequested() || myCursorIsHand)
996       myViewPort->setCursor(myCursor);
997     myCursorIsHand = false;
998   }
999
1000   if (transformRequested())
1001     emit vpTransformationFinished(myOperation);
1002
1003   setTransformInProcess(false);
1004   setTransformRequested(NOTHING);
1005 }
1006
1007 XGUI_ViewBackground XGUI_ViewWindow::background() const
1008 {
1009   return myViewPort ? myViewPort->background() : XGUI_ViewBackground();
1010 }
1011
1012 void XGUI_ViewWindow::setBackground(const XGUI_ViewBackground& theBackground)
1013 {
1014   if (myViewPort) 
1015         myViewPort->setBackground( theBackground );
1016 }
1017
1018 /*!
1019    \brief Create one more window with same content.
1020 */
1021 void XGUI_ViewWindow::cloneView()
1022 {
1023   QMdiSubWindow* vw = myViewer->createView();
1024   XGUI_ViewWindow* aNewWnd = static_cast<XGUI_ViewWindow*>(vw->widget());
1025   aNewWnd->viewPort()->syncronizeWith(myViewPort);
1026
1027   emit viewCloned( vw );
1028
1029   //  In order to avoid frosen background in toolbars when it shown as a second view
1030   QTimer::singleShot(20, vw, SLOT(setFocus()));
1031 }
1032
1033 void XGUI_ViewWindow::dumpView()
1034 {
1035   QString aFilter(tr("Images Files (*.bmp *.png *.jpg *.jpeg *.eps *.ps)"));
1036   QString aSelectedFilter;
1037   QString aFileName = QFileDialog::getSaveFileName(this, "Save picture", QString(), aFilter, &aSelectedFilter);
1038   if (!aFileName.isNull()) {
1039     QApplication::setOverrideCursor( Qt::WaitCursor );
1040     QImage aPicture = myViewPort->dumpView();
1041
1042     QString aFmt = XGUI_Tools::extension(aFileName).toUpper();
1043     if( aFmt.isEmpty() )
1044       aFmt = QString( "BMP" ); // default format
1045     else if( aFmt == "JPG" )
1046       aFmt = "JPEG";
1047
1048     Handle(Visual3d_View) a3dView = myViewPort->getView()->View();
1049     if (aFmt == "PS")
1050       a3dView->Export(strdup(qPrintable(aFileName)), Graphic3d_EF_PostScript);
1051     else if (aFmt == "EPS")
1052       a3dView->Export(strdup(qPrintable(aFileName)), Graphic3d_EF_EnhPostScript);
1053     else
1054       aPicture.save( aFileName, aFmt.toLatin1() );
1055     QApplication::restoreOverrideCursor();
1056   }
1057 }
1058
1059 void XGUI_ViewWindow::fitAll()
1060 {
1061   emit vpTransformationStarted( FITALLVIEW );
1062   myViewPort->fitAll();
1063   emit vpTransformationFinished( FITALLVIEW );
1064 }
1065
1066 /*!
1067   \brief Starts fit operation.
1068
1069   Sets the corresponding cursor for the widget.
1070 */
1071 void XGUI_ViewWindow::activateWindowFit()
1072 {
1073   if ( !transformRequested() && !myCursorIsHand )
1074     myCursor = cursor();                /* save old cursor */
1075
1076   if ( myOperation != WINDOWFIT ) {
1077     QCursor handCursor (Qt::PointingHandCursor);
1078     if( setTransformRequested ( WINDOWFIT ) ) {
1079       myViewPort->setCursor ( handCursor );
1080       myCursorIsHand = true;
1081     }
1082   }
1083 }
1084
1085
1086 /*!
1087   \brief Perform "front view" transformation.
1088 */
1089 void XGUI_ViewWindow::frontView()
1090 {
1091   emit vpTransformationStarted ( FRONTVIEW );
1092   Handle(V3d_View) aView3d = myViewPort->getView();
1093   if ( !aView3d.IsNull() ) 
1094     aView3d->SetProj (V3d_Xpos);
1095   myViewPort->fitAll();
1096   emit vpTransformationFinished ( FRONTVIEW );
1097 }
1098
1099 /*!
1100   \brief Perform "back view" transformation.
1101 */
1102 void XGUI_ViewWindow::backView()
1103 {
1104   emit vpTransformationStarted ( BACKVIEW );
1105   Handle(V3d_View) aView3d = myViewPort->getView();
1106   if ( !aView3d.IsNull() ) 
1107     aView3d->SetProj (V3d_Xneg);
1108   myViewPort->fitAll();
1109   emit vpTransformationFinished ( BACKVIEW );
1110 }
1111
1112 /*!
1113   \brief Perform "top view" transformation.
1114 */
1115 void XGUI_ViewWindow::topView()
1116 {
1117   emit vpTransformationStarted ( TOPVIEW );
1118   Handle(V3d_View) aView3d = myViewPort->getView();
1119   if ( !aView3d.IsNull() ) 
1120     aView3d->SetProj (V3d_Zpos);
1121   myViewPort->fitAll();
1122   emit vpTransformationFinished ( TOPVIEW );
1123 }
1124
1125 /*!
1126   \brief Perform "bottom view" transformation.
1127 */
1128 void XGUI_ViewWindow::bottomView()
1129 {
1130   emit vpTransformationStarted ( BOTTOMVIEW );
1131   Handle(V3d_View) aView3d = myViewPort->getView();
1132   if ( !aView3d.IsNull() ) 
1133     aView3d->SetProj (V3d_Zneg);
1134   myViewPort->fitAll();
1135   emit vpTransformationFinished ( BOTTOMVIEW );
1136 }
1137
1138 /*!
1139   \brief Perform "left view" transformation.
1140 */
1141 void XGUI_ViewWindow::leftView()
1142 {
1143   emit vpTransformationStarted ( LEFTVIEW );
1144   Handle(V3d_View) aView3d = myViewPort->getView();
1145   if ( !aView3d.IsNull() ) 
1146     aView3d->SetProj (V3d_Yneg);
1147   myViewPort->fitAll();
1148   emit vpTransformationFinished ( LEFTVIEW );
1149 }
1150
1151 /*!
1152   \brief Perform "right view" transformation.
1153 */
1154 void XGUI_ViewWindow::rightView()
1155 {
1156   emit vpTransformationStarted ( RIGHTVIEW );
1157   Handle(V3d_View) aView3d = myViewPort->getView();
1158   if ( !aView3d.IsNull() ) 
1159     aView3d->SetProj (V3d_Ypos);
1160   myViewPort->fitAll();
1161   emit vpTransformationFinished ( RIGHTVIEW );
1162 }
1163
1164 void XGUI_ViewWindow::reset()
1165 {
1166   emit vpTransformationStarted( RESETVIEW );
1167   bool upd = myViewPort->getView()->SetImmediateUpdate( false );
1168   myViewPort->getView()->Reset( false );
1169   myViewPort->fitAll( false, true, false );
1170   myViewPort->getView()->SetImmediateUpdate( upd );
1171   myViewPort->getView()->Update();
1172   emit vpTransformationFinished( RESETVIEW );
1173 }
1174
1175
1176 void XGUI_ViewWindow::updateToolBar()
1177 {
1178   myGripWgt->update();
1179   myViewBar->update();
1180   myWindowBar->update();
1181 }
1182
1183 /*!
1184   \brief Update state of enable draw mode state.
1185 */
1186 void XGUI_ViewWindow::updateEnabledDrawMode()
1187 {
1188   myEnableDrawMode = myViewer->isSelectionEnabled() && 
1189                      myViewer->isMultiSelectionEnabled();
1190 }