Salome HOME
SMH: 3.0.0 preparation = merged version (POLYWORK + RTVDEBUG01) + adopation for new GUI
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_CanvasView.cxx
index 2f6f04ece4f8c53d22ed57b7cf2a683d9fba079c..75fe69cc2fe31e13f914e580ea7cedd93bbb89d8 100644 (file)
@@ -9,13 +9,16 @@
 //  Module : SUPERV
 
 using namespace std;
+
 #include "SUPERVGUI_CanvasView.h"
 #include "SUPERVGUI_Main.h"
 #include "SUPERVGUI_CanvasNode.h"
 #include "SUPERVGUI_CanvasPort.h"
 #include "SUPERVGUI_CanvasLink.h"
 #include "SUPERVGUI_CanvasNodePrs.h"
-#include "QAD_Config.h"
+#include "SUPERVGUI_Clipboard.h"
+
+#include "SUIT_MessageBox.h"
 
 #include <qpixmap.h>
 #include <qcolordialog.h>
@@ -64,6 +67,7 @@ const char* imageZoomCursor[] = {
 
 QPixmap zoomPix(imageZoomCursor);
 QCursor zoom2Cursor(zoomPix);
+QCursor handCursor(Qt::PointingHandCursor);
 
 #if QT_VERSION >= 0x030005
 QCursor pan2Cursor(Qt::SizeAllCursor);
@@ -77,11 +81,14 @@ SUPERVGUI_CanvasView::SUPERVGUI_CanvasView(SUPERVGUI_Canvas* theCanvas, SUPERVGU
 {
   setName("CanvasView");
 
+  myIsPanBtnClicked = false;
   myIsPanActivated = false;
+  myIsFitWRActivated = false;
   myIsZoomActivated = false;
   myIsLinkCreating = false;
 
   myAddStudyItem = 0;
+  mySelectedRect = 0;
   myCursor = cursor();
 
   myTimer = new QTimer(this);
@@ -89,19 +96,22 @@ SUPERVGUI_CanvasView::SUPERVGUI_CanvasView(SUPERVGUI_Canvas* theCanvas, SUPERVGU
 
   myPopup = new QPopupMenu(viewport());
 
-  if (myMain->isEditable()) {
+  const bool isEdit = myMain->isEditable();
+  if (isEdit) {
     myPopup->insertItem(tr("MSG_ADD_NODE"), myMain, SLOT(addNode()));
+
+    // Paste Node functionality
+    SUPERVGUI_Clipboard* aCB = SUPERVGUI_Clipboard::getClipboard();
+    myPasteNodeItem = myPopup->insertItem(tr("ITM_PASTE_NODE"), aCB, SLOT(pasteNode()));
+
     myPopup->insertItem(tr("MSG_INS_FILE"), myMain, SLOT(insertFile()));
     myPopup->insertSeparator();
   }
 
   QPopupMenu* aViewPopup = new QPopupMenu(viewport());
-  //  aViewPopup->insertItem(tr("POP_FULLVIEW"), myMain, SLOT(showFullGraph()));
   aViewPopup->insertItem(tr("POP_FULLVIEW"), myMain, SLOT(showCanvas()));
   aViewPopup->insertItem(tr("POP_CONTROLVIEW"), myMain, SLOT(showContolFlow()));
-  aViewPopup->insertItem(tr("POP_TABLEVIEW"), myMain, SLOT(showTable()));
-  //  aViewPopup->insertItem("Previous Full View", myMain, SLOT(showFullGraph()));
-  //  aViewPopup->insertItem(tr("POP_CANVASVIEW"), myMain, SLOT(showCanvas()));
+  aViewPopup->insertItem(tr("POP_TABLEVIEW"), myMain, SLOT(showCanvasTable()));
 
   myPopup->insertItem(tr("POP_VIEW"), aViewPopup);
   myPopup->insertSeparator();
@@ -111,13 +121,17 @@ SUPERVGUI_CanvasView::SUPERVGUI_CanvasView(SUPERVGUI_Canvas* theCanvas, SUPERVGU
   aZoomPopup->insertItem("100%", this, SLOT(zoomReset()));
   aZoomPopup->insertItem("50%", this, SLOT(zoomOut()));
   aZoomPopup->insertSeparator();
-  aZoomPopup->insertItem("Fit All", this, SLOT(fitAll()));
+  //mkr: "Fit within rectangle" functionality
+  aZoomPopup->insertItem(tr("POP_FITWITHINRECT"), this, SLOT(fitWithinRect()));
+  aZoomPopup->insertSeparator();
+  aZoomPopup->insertItem(tr("POP_FITALL"), this, SLOT(fitAll()));
+  
 
-  myPopup->insertItem("Zoom", aZoomPopup);
+  myPopup->insertItem(tr("POP_ZOOM"), aZoomPopup);
   myPopup->insertSeparator();
 
-  myAddStudyItem = myPopup->insertItem(tr("MSG_ADD_STUDY"), this, SLOT(addToStudy()));
-  myPopup->insertItem(tr("MSG_CHANGE_INFO"), myMain, SLOT(changeInformation()));
+  myAddStudyItem = myPopup->insertItem(tr("MSG_ADD_STUDY"), myMain, SLOT(addDataflowToStudy()));
+  myPopup->insertItem(tr(isEdit ? "MSG_CHANGE_INFO" : "MSG_INFO"), myMain, SLOT(changeInformation()));
   myPopup->insertSeparator();
 
   myPopup->insertItem(tr("MSG_COPY_DATAFLOW"), myMain, SLOT(copy()));
@@ -143,7 +157,6 @@ SUPERVGUI_CanvasView::~SUPERVGUI_CanvasView()
 
 void SUPERVGUI_CanvasView::contentsMousePressEvent(QMouseEvent* theEvent) 
 {
-  //  cout << "===> SUPERVGUI_CanvasView::contentsMousePressEvent(...) "   << endl;
   myPoint = inverseWorldMatrix().map(theEvent->pos());
   myGlobalPoint = theEvent->globalPos();
   myCurrentItem = 0;
@@ -153,7 +166,7 @@ void SUPERVGUI_CanvasView::contentsMousePressEvent(QMouseEvent* theEvent)
 
   if (((theEvent->button() == Qt::MidButton) &&
        (theEvent->state() == Qt::ControlButton)) || 
-      myIsPanActivated) {
+      myIsPanBtnClicked) {
     myIsPanActivated = true;
     myCursor = cursor();
     setCursor(pan2Cursor);
@@ -207,46 +220,51 @@ void SUPERVGUI_CanvasView::contentsMousePressEvent(QMouseEvent* theEvent)
       }
     }
        
-    myPopup->setItemEnabled(myAddStudyItem, !myMain->isFromStudy());
+    myPopup->setItemEnabled(myAddStudyItem, !myMain->isDataflowInStudy());
+    // Paste Node functionality
+    SUPERVGUI_Clipboard* aCB = SUPERVGUI_Clipboard::getClipboard(); 
+    myPopup->setItemEnabled(myPasteNodeItem, aCB->isCopyNode() );
     myMain->showPopup(myPopup, theEvent);
     return;
   }
 
   if (theEvent->button() == Qt::LeftButton) {
-    QCanvasItemList l = canvas()->collisions(myPoint);
-    if (myIsLinkCreating) {
-      for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
-       if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
-         SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
-         QObject* anObj = aNodePrs->getObject(myPoint);
-         if (anObj->inherits("SUPERVGUI_CanvasPort")) {
-           endSketch((SUPERVGUI_CanvasPort*)anObj);
-           return;
+    if (!myIsFitWRActivated) {//not moving items if fit within rectangle 
+                              //functionality is enable
+      QCanvasItemList l = canvas()->collisions(myPoint);
+      if (myIsLinkCreating) {
+       for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
+         if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
+           SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
+           QObject* anObj = aNodePrs->getObject(myPoint);
+           if (anObj->inherits("SUPERVGUI_CanvasPort")) {
+             endSketch((SUPERVGUI_CanvasPort*)anObj);
+             return;
+           }
+           else {
+             myCurrentItem = *it;
+             ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
+             ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
+             return;
+           }
          }
-         else {
-           myCurrentItem = *it;
-           ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
-           ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
-           return;
+         if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Hook) {
+           SUPERVGUI_CanvasHookPrs* aHookPrs = (SUPERVGUI_CanvasHookPrs*) (*it);
+           QObject* anObj = aHookPrs->getObject();
+           if (anObj->inherits("SUPERVGUI_CanvasPort")) {
+             endSketch((SUPERVGUI_CanvasPort*)anObj);
+             return;
+           }
          }
        }
-       if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Hook) {
-         SUPERVGUI_CanvasHookPrs* aHookPrs = (SUPERVGUI_CanvasHookPrs*) (*it);
-         QObject* anObj = aHookPrs->getObject();
-         if (anObj->inherits("SUPERVGUI_CanvasPort")) {
-           endSketch((SUPERVGUI_CanvasPort*)anObj);
-           return;
-         }
+       if (myLinkBuilder) {
+         myLinkBuilder->addNextPoint(myPoint, mySketchPopup->isItemChecked(myOrtoItem));
+         canvas()->update();
+         mySketchPopup->setItemEnabled(myDelPntItem, true);
+         return;
        }
       }
-      if (myLinkBuilder) {
-       myLinkBuilder->addNextPoint(myPoint, mySketchPopup->isItemChecked(myOrtoItem));
-       canvas()->update();
-       mySketchPopup->setItemEnabled(myDelPntItem, true);
-       return;
-      }
-    }
-
+      
 //  if (myMain->isEditable()) { // allow to move nodes and link point on imported graph
       for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
        if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
@@ -263,8 +281,25 @@ void SUPERVGUI_CanvasView::contentsMousePressEvent(QMouseEvent* theEvent)
            return;
          }
        }
+       if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
+         //mkr: for moving segment of link
+         SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
+         if (aPrs->getLink()->getInputPort()->getConnectionPoint() == aPrs->startPoint()
+             ||
+           aPrs->getLink()->getInputPort()->getConnectionPoint() == aPrs->endPoint()
+             ||
+             aPrs->getLink()->getOutputPort()->getConnectionPoint() == aPrs->startPoint()
+             ||
+             aPrs->getLink()->getOutputPort()->getConnectionPoint() == aPrs->endPoint()) {
+           return;
+         }
+         myCurrentItem = *it;
+         aPrs->setMoving(true);
+         return;
+       }
       }
 //  }
+    } 
   }
 }
 
@@ -287,10 +322,13 @@ void SUPERVGUI_CanvasView::contentsMouseMoveEvent(QMouseEvent* theEvent)
       
   if (myCurrentItem) {
     //    setHilighted(0);
-    double cx = myCurrentItem->x() - myPoint.x();
-    double cy = myCurrentItem->y() - myPoint.y();
-    if (p.x()+cx < 0) p.setX(-(int)cx);
-    if (p.y()+cy < 0) p.setY(-(int)cy);
+    if (myCurrentItem->x() && myCurrentItem->y()) {
+      double cx = myCurrentItem->x() - myPoint.x();
+      double cy = myCurrentItem->y() - myPoint.y();
+      
+      if (p.x()+cx < 0) p.setX(-(int)cx);
+      if (p.y()+cy < 0) p.setY(-(int)cy);
+    }
     myCurrentItem->moveBy(p.x() - myPoint.x(), 
                          p.y() - myPoint.y());
     myPoint = p;
@@ -337,6 +375,30 @@ void SUPERVGUI_CanvasView::contentsMouseMoveEvent(QMouseEvent* theEvent)
     return;
   }
 
+  //mkr: "Fit within rectangle" functionality
+  if (myIsFitWRActivated) {
+    int aLX, aTY; //left x and top y
+    if (myPoint.x() < p.x()) aLX = myPoint.x();
+    else aLX = p.x();
+    if (myPoint.y() < p.y()) aTY = myPoint.y();
+    else aTY = p.y();
+    QRect aRect(aLX, aTY, abs(myPoint.x()-p.x()), abs(myPoint.y()-p.y()));
+    QCanvasRectangle* aRect1 = new QCanvasRectangle(aRect, canvas());
+
+    //hide old selected rectangle
+    if (mySelectedRect)
+      mySelectedRect->hide();
+    //draw new selected rectangle
+    QPen pen(Qt::SolidLine);
+    pen.setWidth(1);
+    aRect1->setPen(pen);
+    aRect1->setZ(3);
+    aRect1->show();
+
+    mySelectedRect = aRect1;
+    canvas()->update();
+  }
+  
   if (!myIsLinkCreating && myMain->isEditable() &&
       !myMain->getCanvas()->isControlView()) {
     // compute collision rectangle
@@ -364,7 +426,6 @@ void SUPERVGUI_CanvasView::contentsMouseMoveEvent(QMouseEvent* theEvent)
 
 void SUPERVGUI_CanvasView::contentsMouseReleaseEvent(QMouseEvent* theEvent) 
 {
-  //  cout << "===> SUPERVGUI_CanvasView::contentsMouseReleaseEvent(...) "   << endl;
   if (myTimer->isActive()) myTimer->stop();
 
   if (myCurrentItem) {
@@ -381,6 +442,7 @@ void SUPERVGUI_CanvasView::contentsMouseReleaseEvent(QMouseEvent* theEvent)
 
   if (myIsPanActivated) {
     myIsPanActivated = false;
+    myIsPanBtnClicked = false;
     setCursor(myCursor);
   }
 
@@ -388,15 +450,47 @@ void SUPERVGUI_CanvasView::contentsMouseReleaseEvent(QMouseEvent* theEvent)
     myIsZoomActivated = false;
     setCursor(myCursor);
   }
+
+  //mkr: "Fit within rectangle" functionality
+  if (myIsFitWRActivated) {
+    if (mySelectedRect) {
+      mySelectedRect->hide();
+      mySelectedRect = 0;
+      canvas()->update();
+    }
+
+    //myPoint is the start point for selecting rectangle now
+    QPoint anEndPoint = inverseWorldMatrix().map(theEvent->pos());
+    int aLX, aTY; //left x and top y
+    if (myPoint.x() < anEndPoint.x()) aLX = myPoint.x();
+    else aLX = anEndPoint.x();
+    if (myPoint.y() < anEndPoint.y()) aTY = myPoint.y();
+    else aTY = anEndPoint.y();
+
+    //calculate width and height for new view and new zoom factor
+    double aXzoom = ((double)visibleWidth())/((double)(abs(myPoint.x()-anEndPoint.x())));
+    double aYzoom = ((double)visibleHeight())/((double)(abs(myPoint.y()-anEndPoint.y())));
+    if (aXzoom > aYzoom) aXzoom = aYzoom;
+    
+    QWMatrix m;
+    m.scale(aXzoom, aXzoom);
+    setWorldMatrix(m);
+    setContentsPos((int)(aLX*aXzoom), (int)(aTY*aYzoom));
+
+    canvas()->update();
+    
+    myIsFitWRActivated = false;
+    viewport()->setMouseTracking(true);
+    setCursor(myCursor);
+  }
 }
 
 void SUPERVGUI_CanvasView::contentsMouseDoubleClickEvent(QMouseEvent* theEvent)
 {
-  //  cout << "===> SUPERVGUI_CanvasView::contentsMouseDoubleClickEvent(...) "   << endl;
   QPoint p = inverseWorldMatrix().map(theEvent->pos());
 
   // compute collision rectangle
-  QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
+  //QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
 
   if (theEvent->button() == Qt::LeftButton) {
     QCanvasItemList l = canvas()->collisions(p);
@@ -461,7 +555,7 @@ void SUPERVGUI_CanvasView::changeBackground()
 
 void SUPERVGUI_CanvasView::ActivatePanning()
 {
-  myIsPanActivated = true;
+  myIsPanBtnClicked = true;
 }
 
 void SUPERVGUI_CanvasView::ResetView()
@@ -482,7 +576,6 @@ void SUPERVGUI_CanvasView::startSketch(SUPERVGUI_CanvasPort* thePort)
 
 void SUPERVGUI_CanvasView::endSketch(SUPERVGUI_CanvasPort* thePort)
 {
-  //  cout << "===> SUPERVGUI_CanvasView::endSketch(" << thePort->name() << ")"  << endl;
   if (!myIsLinkCreating) return;
 
   if (myLinkBuilder && myLinkBuilder->canCreateEngine(thePort)) {
@@ -507,7 +600,43 @@ void SUPERVGUI_CanvasView::endSketch(SUPERVGUI_CanvasPort* thePort)
       SUPERVGUI_CanvasPort* aOutPort = (input ? myLinkBuilder->getStartPort() : thePort);
       aLinkEngine = myMain->getDataflow()->Link(aOutPort->getEngine(), aInPort->getEngine());
     }
-    if (SUPERV_isNull(aLinkEngine)) return;
+    if (SUPERV_isNull(aLinkEngine)) 
+      return;    
+
+    // here, in fact, aLinkEngine may NOT be a newly created link.  If a link already existed between the
+    // the 2 given ports - it will be return (NOT created again).
+    // this should be checked and new presentation should NOT be created for existing link.
+    // Solution 1: NOT to allow creation of a link if it already exists between the ports in 
+    //             myLinkBuilder->canCreateEngine()
+    // Solution 2: check here if aLinkEngine is "new" or "old"
+    // Implement 2nd solution, because canCreateEngine() checks for types of ports, etc.. - it's another thing
+    // THE CHECK:
+    QObjectList* canvasLinks = canvas()->queryList("SUPERVGUI_CanvasLink");
+    SUPERVGUI_CanvasLink* canvasLink = 0;
+    QObjectListIt it(*canvasLinks);
+    bool prsAlreadyExists = false;
+    while ( (canvasLink=(SUPERVGUI_CanvasLink*)it.current()) ) {
+      ++it;
+      SUPERV_Link existingLinkWithPrs = canvasLink->getEngine();
+      if ( !SUPERV_isNull( existingLinkWithPrs ) ) {
+       if ( existingLinkWithPrs->IsEqual( aLinkEngine ) ) {
+         prsAlreadyExists = true;
+         break;
+       }       
+      }
+    }
+    delete canvasLinks;
+    if ( prsAlreadyExists ) { // aLinkEngine is already bound with a SUPERVGUI_CanvasLink object
+      //return;  // -> if return here, than the old CanvasLink is kept
+
+      // we want to delete old and create a new CanvasLink for this Link
+      delete canvasLink;
+      canvasLink = 0;
+      // clear old corrdinates in Engine link
+      for ( int i = 1; i <= aLinkEngine->CoordsSize(); i++ )
+       aLinkEngine->RemoveCoord( i );
+      // now we are ready to set coords for a link and create a new CanvasLink presentation that will use them.
+    }
 
     myLinkBuilder->setCoords(aLinkEngine.in());
 
@@ -519,6 +648,15 @@ void SUPERVGUI_CanvasView::endSketch(SUPERVGUI_CanvasPort* thePort)
 
     canvas()->update();
     myIsLinkCreating = false;
+
+    // asv : 13.12.04 : introducing a check for ports' types compatibility (Bugs and Improvements p.1.16, PAL7380)
+    if ( !aLinkEngine->IsValid() ) { 
+      const int id = SUIT_MessageBox::warn2( this, tr( "TLT_INVALID_LINK" ), tr( "MSG_INVALID_LINK" ), 
+                                            tr( "Keep" ), tr( "Remove" ), 0, 1, 0 );
+      if ( id == 1 ) { // "Remove" was selected in Message Box
+       aLink->remove(); // the new link did not live long...
+      }
+    }
   }
 }
 
@@ -547,12 +685,6 @@ void SUPERVGUI_CanvasView::setOrthoMode()
   mySketchPopup->setItemChecked(myOrtoItem, aIsOrtho);
 }
 
-
-void SUPERVGUI_CanvasView::addToStudy() 
-{
-  if (myMain->addStudy()) myMain->setAsFromStudy(true);
-}
-
 void SUPERVGUI_CanvasView::zoomIn() 
 {
   QWMatrix m;
@@ -597,3 +729,12 @@ void SUPERVGUI_CanvasView::fitAll()
   setWorldMatrix(m);
   canvas()->update();
 }
+
+void SUPERVGUI_CanvasView::fitWithinRect() 
+{
+  //mkr: "Fit within rectangle" functionality
+  myIsFitWRActivated = true;
+  viewport()->setMouseTracking(false);
+  myCursor = cursor();
+  setCursor(handCursor);
+}