Salome HOME
Patch from Christian CAREMOLI for bug PAL10339 : random GUI freeze.
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_Main.cxx
index e8c624e77755cbb1f4c96c299bdeb0e638c0e522..4bbdb9e5e2ba19273902f20ef74d800f66793daf 100644 (file)
@@ -244,6 +244,13 @@ void SUPERVGUI_Main::filterNotification() {
   }
 }
 
+void SUPERVGUI_Main::changeDSGraphParameters() {
+  SUPERVGUI_DSGraphParameters* aDlg = new SUPERVGUI_DSGraphParameters(dataflow, dataflow->IsReadOnly());
+  if (aDlg->exec() )
+    sync();
+  delete aDlg;
+}
+
 void SUPERVGUI_Main::syncAsync() {
   Trace("SUPERVGUI_Main::syncAsync");
   QTimer::singleShot(1, this, SLOT(sync()));
@@ -898,7 +905,8 @@ _PTR(SObject) createDataflowSObj( SUIT_Study* study,
   if ( !aSO ) { // dataflow SObject not found in the study
     aDoneSomething = true; 
     _PTR(SComponent) aComponent = aStudy->FindComponent(STUDY_SUPERVISION);
-    if ( aComponent ) { // if component found, create name and icon for it to display it in object browser
+    if ( !aComponent ) { // is supervision component not found, then create it
+      aComponent = aBuilder->NewComponent(STUDY_SUPERVISION);
       anAttr = aBuilder->FindOrCreateAttribute(aComponent, "AttributeName");
       aName = anAttr;
       aName->SetValue( (( CAM_Application* )(study->application()))->moduleTitle( "SUPERV" ).latin1() );
@@ -955,6 +963,8 @@ void SUPERVGUI_Main::addDataflowToStudy() {
 bool SUPERVGUI_Main::putDataStudy( SUPERV_Port p, const char* inout ) {
   Trace("SUPERVGUI_Main::putDataStudy");
 
+  bool PublishOtherComponent = false;
+
   // static variable to ensure that only one instance (thread) is executing this function 
   static bool isIn = false;
   if (isIn)   return true; 
@@ -1034,6 +1044,7 @@ bool SUPERVGUI_Main::putDataStudy( SUPERV_Port p, const char* inout ) {
            if ( !aSStudy ) return false;
            aTmpSO = aDriver->PublishInStudy( aSStudy->GetStudy(), aTmpSO, anObject, "" );
            aBuilder->Addreference(aSO, _PTR(SObject)(new SALOMEDS_SObject( aTmpSO )) );
+           PublishOtherComponent = true;
          } 
          else { // can't publish object: abort transaction
            MESSAGE( "CanPublishInStudy() returned FALSE.  ok, AbortCommand.." );
@@ -1044,8 +1055,11 @@ bool SUPERVGUI_Main::putDataStudy( SUPERV_Port p, const char* inout ) {
        }
        else { // component has no driver, but could store IORs (like Calculator)
          _PTR(SObject) anIORSO ( aStudy->FindObjectIOR( p->ToString() ) );
-         if ( anIORSO )
+         if ( anIORSO ) {
            aBuilder->Addreference(aSO, anIORSO);
+           // mkr : IPAL9672
+           PublishOtherComponent = true;
+         }
          else { // Hm... the object (==port value) was not found, so we don't publish it.
            MESSAGE( "The object (==port value) was not found, so we don't publish it" );
            aBuilder->AbortCommand();
@@ -1055,10 +1069,18 @@ bool SUPERVGUI_Main::putDataStudy( SUPERV_Port p, const char* inout ) {
        }
       }
       else { // FNode is NULL -> bad
-       MESSAGE( "FNode is NULL.  Not good at all.  Aborting command." );
-       aBuilder->AbortCommand();
-       isIn = false;
-       return false;
+       MESSAGE( "FNode is NULL." );
+       if ( SUPERV::INode::_narrow( p->Node() ) ) { // mkr : IPAL10175
+         _PTR(SObject) anIORSO ( aStudy->FindObjectIOR( p->ToString() ) );
+         if ( anIORSO )
+           aBuilder->Addreference(aSO, anIORSO);
+       }
+       else {
+         MESSAGE( "FNode and INode are NULL.  Not good at all.  Aborting command." );
+         aBuilder->AbortCommand();
+         isIn = false;
+         return false;
+       }
       }
     } 
     else {
@@ -1070,14 +1092,16 @@ bool SUPERVGUI_Main::putDataStudy( SUPERV_Port p, const char* inout ) {
     aBuilder->CommitCommand();
   else
     aBuilder->AbortCommand();
-  
-  if ( !myThread->running() ) {
-    SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
-    if ( aSupMod ) 
+
+  SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
+  if ( aSupMod ) {
+    if ( PublishOtherComponent )
+      dynamic_cast<SalomeApp_Application*>( study->application() )->updateObjectBrowser(true);
+    else
       aSupMod->updateObjBrowser();
-    else MESSAGE("NULL Supervision module!");
   }
-
+  else MESSAGE("NULL Supervision module!");
+  
   isIn = false;
   return true;
 }
@@ -1113,14 +1137,14 @@ void SUPERVGUI_Main::syncNotification() {
   long  stamp;
   
   while (notification->Receive(&graph, &node, &type, &message, &sender, &counter, &date, &stamp)) {
-    if (isFiltered(graph, node, type, message, sender, counter, date, stamp)) {
+//    if (isFiltered(graph, node, type, message, sender, counter, date, stamp)) {
       QString mess("");
       mess += "NOTIF: "; mess += graph;
       mess += " / "    ; mess += node;
       mess += " / "    ; mess += type;
       mess += " / "    ; mess += message;
       getMessage()->putMessage(mess.latin1());
-    };
+//    };
   };
 }
   
@@ -1277,6 +1301,20 @@ bool SUPERVGUI_Main::ReadyToModify() {
   return true;
 }
 
+void SUPERVGUI_Main::resizeView( QResizeEvent* theEvent )
+{
+  if ( (myCurrentView == CANVAS || myCurrentView == CONTROLFLOW) && getCanvas() )
+    if ( getCanvas()->width() < theEvent->size().width()
+        ||
+        getCanvas()->height() < theEvent->size().height() )
+      getCanvas()->resize( theEvent->size().width(), theEvent->size().height() );
+  if ( myCurrentView == CANVASTABLE && getCanvasArray() )
+    if ( getCanvasArray()->width() < theEvent->size().width()
+        ||
+        getCanvasArray()->height() < theEvent->size().height() )
+      getCanvasArray()->resize( theEvent->size().width(), theEvent->size().height() );
+}
+
 /******************************* SUPERVGUI_Thread class ****************************************/
 SUPERVGUI_Thread::SUPERVGUI_Thread()
      :QThread()
@@ -1313,66 +1351,105 @@ void SUPERVGUI_Thread::KillThread( bool theValue )
   myMutex.unlock();
 }
 
-typedef TVoidMemFun2ArgEvent<SUPERVGUI_Main, char*, SUPERV::GraphState> TNodeSyncEvent;
-
-void SUPERVGUI_Thread::run()
-{
-  myMain->startTimer();
-
-  // GUI cycle to handle events coming for Engine
-  while ( myIsActive ) {
+template<class TObject, typename TArg, typename TArg1, typename TArg2,
+        typename TStoreArg = TArg, typename TStoreArg1 = TArg1, typename TStoreArg2 = TArg2>
+class TVoidMemFun3ArgEvent: public SALOME_Event{
+public:
+  typedef void (TObject::* TAction)(TArg,TArg1,TArg2);
+  TVoidMemFun3ArgEvent(TObject* theObject, TAction theAction, TArg theArg, TArg1 theArg1, TArg2 theArg2):
+    myObject(theObject),
+    myAction(theAction),
+    myArg(theArg),
+    myArg1(theArg1),
+    myArg2(theArg2)
+  {}
+  virtual void Execute(){
+    (myObject->*myAction)(myArg,myArg1,myArg2);
+  }
+private:
+  TObject* myObject;
+  TAction myAction;
+  TStoreArg myArg;
+  TStoreArg1 myArg1;
+  TStoreArg2 myArg2;
+};
 
-    SUPERV_CNode aNode = NULL;
-    SUPERV::GraphEvent aEvent = SUPERV::UndefinedEvent ;
-    SUPERV::GraphState aState = SUPERV::UndefinedState ;
+typedef TVoidMemFun3ArgEvent<SUPERVGUI_Thread, SUPERV_CNode&, SUPERV::GraphEvent&, SUPERV::GraphState&> TMainRunEvent;
 
-    // blocking function of Engine.  Return from there only after anEvent happens on node aNode
-    myMain->getDataflow()->Event(aNode, aEvent, aState);
+/**
+ * main_thread_run must be executed in the qt main thread
+ * It is activated by calling ProcessVoidEvent
+ */
+void SUPERVGUI_Thread::main_thread_run(SUPERV_CNode& aNode, SUPERV::GraphEvent& aEvent, SUPERV::GraphState& aState)
+{
+    // in case node "said" something during changing state through notification mechanism - output it
+    myMain->syncNotification();
     
     // "kill" or undefined event came
     if (( aEvent == SUPERV::UndefinedEvent && aState == SUPERV::UndefinedState ) ||
-       ( aEvent == SUPERV::NoEvent && aState == SUPERV::NoState ) ||
-       ( aEvent == SUPERV::KillEvent && aState == SUPERV::KillState )) {
+       ( aEvent == SUPERV::NoEvent && aState == SUPERV::NoState ) ||
+       ( aEvent == SUPERV::KillEvent && aState == SUPERV::KillState )) {
 
       myIsActive = false;
     }
     else { // a "normal" execution event came
       char* aName = NULL;
       if ( aNode != NULL && !CORBA::is_nil( aNode ) ) 
-       aName = aNode->Name();      
+       aName = aNode->Name();      
 
+      // What follow is not quite sure. The entire function is posted to the main qt thread.
+      // So all executions are serialized. Is it really possible to call execute when another
+      // execute is running. I don't think so (C Caremoli)
       // this function is asynchronious.  The call does NOT wait when SUPERVGUI_Main::execute finishes
       // handling the event.  So: SUPERVGUI_Main::execute must be fast, in order we don't get here again
       // on the next loop iteration, BEFORE  previous SUPERVGUI_Main::execute finished.
-      ProcessVoidEvent( new TNodeSyncEvent( myMain, &SUPERVGUI_Main::execute, aName, aState ) );
+      myMain->execute(aName, aState );
     }    
-  
+
     // execution is finished.  just set a "finished" message(s)
     if ( !myIsActive ) {
       switch ( myMain->getDataflow()->State() ) {
       case SUPERV_Editing :     
-       myMain->getMessage()->putMessage( myMain->getDataflow()->IsReadOnly()? 
-                                        tr("MSG_GRAPH_READONLY"): tr("MSG_GRAPH_EDITING") );
-       break;  
+       myMain->getMessage()->putMessage( myMain->getDataflow()->IsReadOnly()? 
+                                        tr("MSG_GRAPH_READONLY"): tr("MSG_GRAPH_EDITING") );
+       break;  
       case SUPERV_Suspend : 
-       myMain->getMessage()->putMessage( tr("MSG_GRAPH_SUSPENDED") );
-       break; 
+       myMain->getMessage()->putMessage( tr("MSG_GRAPH_SUSPENDED") );
+       break; 
       case SUPERV_Done : 
-       myMain->getMessage()->putMessage( tr("MSG_GRAPH_FINISHED") );
-       break;  
+       myMain->getMessage()->putMessage( tr("MSG_GRAPH_FINISHED") );
+       break;  
       case SUPERV_Error :
-       myMain->getMessage()->putMessage( tr("MSG_GRAPH_ABORTED") );
-       break;  
+       myMain->getMessage()->putMessage( tr("MSG_GRAPH_ABORTED") );
+       break;  
       case SUPERV_Kill:
-       myMain->getMessage()->putMessage( tr("MSG_GRAPH_KILLED") );
-       break;
+       myMain->getMessage()->putMessage( tr("MSG_GRAPH_KILLED") );
+       break;
       } // end of switch
 
       // asv 03.02.05 : fix for PAL6859, not very good, but works..
       myMain->sync();
     } // end of if !myIsActive
-  } // end of while( myIsActive )
+}
 
+void SUPERVGUI_Thread::run()
+{
+  myMain->startTimer();
+  
+  // GUI cycle to handle events coming for Engine
+  while ( myIsActive ) {
+    
+    SUPERV_CNode aNode = NULL;
+    SUPERV::GraphEvent aEvent = SUPERV::UndefinedEvent ;
+    SUPERV::GraphState aState = SUPERV::UndefinedState ;
+    
+    // blocking function of Engine.  Return from there only after anEvent happens on node aNode
+    myMain->getDataflow()->Event(aNode, aEvent, aState);
+    
+    ProcessVoidEvent( new TMainRunEvent( this, &SUPERVGUI_Thread::main_thread_run,aNode, aEvent, aState ) );
+    
+  } // end of while( myIsActive )
+  
   QThread::exit();
 }