Salome HOME
Upgrade to paraview 5.4
[modules/gui.git] / src / SALOME_PYQT / SALOME_PYQT_GUILight / SALOME_PYQT_PyModule.cxx
index 30bd9616e86d17ff13836ca5ea8bda47258a939b..459839a9b74c549636310023d832868e505a5644 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -65,6 +65,9 @@ const int DEFAULT_GROUP = 40;
 */
 QMutex myInitMutex;
 
+/*! DEBUG mode */
+const bool DEBUG = false;
+
 /*!
   \var IsCallOldMethods
   \brief Allow calling obsolete callback methods.
@@ -165,15 +168,18 @@ public:
   FuncMsg( const QString& funcName )
   {
     myName = funcName;
-    MESSAGE( qPrintable( myName ) << " [ begin ]" );
+    if ( DEBUG )
+      MESSAGE( qPrintable( myName ) << " [ begin ]" );
   }
   ~FuncMsg()
   {
-    MESSAGE( qPrintable( myName ) << " [ end ]" );
+    if ( DEBUG )
+      MESSAGE( qPrintable( myName ) << " [ end ]" );
   }
   void message( const QString& msg )
   {
-    MESSAGE( qPrintable( myName ) << " : " << qPrintable( msg ) );
+    if ( DEBUG )
+      MESSAGE( qPrintable( myName ) << " : " << qPrintable( msg ) );
   }
 private:
   QString myName;
@@ -1156,6 +1162,44 @@ void PyModuleHelper::actionActivated()
   PyInterp_Dispatcher::Get()->Exec( new ActionReq( myInterp, this, myModule->actionId( action ) ) );
 }
 
+/*!
+  \brief update selection from other views or modules.
+
+  Called when selection is modified outside.
+*/
+void PyModuleHelper::selectionUpdated(const QStringList& entries)
+{
+  FuncMsg fmsg( "PyModuleHelper::selectionUpdated()" );
+  MESSAGE("selectionUpdated");
+
+  // perform synchronous request to Python event dispatcher
+  class SelectionReq : public PyInterp_LockRequest
+  {
+  public:
+    SelectionReq( PyInterp_Interp* _py_interp,
+                  PyModuleHelper*  _helper,
+                  const QStringList& _entries )
+      : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
+        myHelper( _helper ),
+        myEntries( _entries  )
+    {
+      MESSAGE("SelectionReq");
+    }
+  protected:
+    virtual void execute()
+    {
+      MESSAGE("execute");
+      myHelper->internalSelectionUpdated( myEntries );
+    }
+  private:
+    PyModuleHelper* myHelper;
+    const QStringList& myEntries;
+  };
+
+  // post request
+  PyInterp_Dispatcher::Get()->Exec( new SelectionReq( myInterp, this, entries ) );
+}
+
 /*!
   \brief Process context popup menu request.
   
@@ -1368,8 +1412,9 @@ void PyModuleHelper::cloneView( SUIT_ViewWindow* view )
 /*!
   \brief Save module data. Called when user saves study.
   \param files output list of files where module stores data
+  \param url study URL
 */
-void PyModuleHelper::save( QStringList& files )
+void PyModuleHelper::save( QStringList& files, const QString& url )
 {
   FuncMsg fmsg( "PyModuleHelper::save()" );
 
@@ -1385,33 +1430,38 @@ void PyModuleHelper::save( QStringList& files )
   public:     
     SaveReq( PyInterp_Interp* _py_interp,
              PyModuleHelper*  _helper,
-             QStringList&     _files )
+             QStringList&     _files,
+             const QString&   _url )
       : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
         myHelper( _helper ) ,
-        myFiles( _files )
+        myFiles( _files ),
+        myUrl( _url )
     {}
   protected:
     virtual void execute()
     {
-      myHelper->internalSave( myFiles );
+      myHelper->internalSave( myFiles, myUrl );
     }
   private:
     PyModuleHelper* myHelper;
     QStringList&    myFiles;
+    QString         myUrl;
   };
   
   // Posting the request only if dispatcher is not busy!
   // Executing the request synchronously
   if ( !PyInterp_Dispatcher::Get()->IsBusy() )
-    PyInterp_Dispatcher::Get()->Exec( new SaveReq( myInterp, this, files ) );
+    PyInterp_Dispatcher::Get()->Exec( new SaveReq( myInterp, this, files, url ) );
 }
 
 /*
- \brief Load module data. Called when user opens study 
- and activates module.
- \param files list of files where module data is stored
+  \brief Load module data. Called when user opens study 
+  and activates module.
+  \param files list of files where module data is stored
+  \param url study URL
+  \return \c true if loading has been finished successfully or \c false otherwise
 */
-bool PyModuleHelper::load( const QStringList& files )
+bool PyModuleHelper::load( const QStringList& files, const QString& url )
 {
   FuncMsg fmsg( "PyModuleHelper::load()" );
 
@@ -1423,27 +1473,30 @@ bool PyModuleHelper::load( const QStringList& files )
     LoadReq( PyInterp_Interp* _py_interp,
              PyModuleHelper*  _helper,
              QStringList      _files,
+             const QString&   _url,
              bool&            _loaded )
       : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
         myHelper( _helper ) ,
         myFiles( _files ),
+        myUrl( _url ),
         myLoaded( _loaded )
     {}
   protected:
     virtual void execute()
     {
-      myHelper->internalLoad( myFiles, myLoaded );
+      myHelper->internalLoad( myFiles, myUrl, myLoaded );
     }
   private:
     PyModuleHelper* myHelper;
     QStringList     myFiles;
+    QString         myUrl;
     bool&           myLoaded;
   };
   
   // Posting the request only if dispatcher is not busy!
   // Executing the request synchronously
   if ( !PyInterp_Dispatcher::Get()->IsBusy() )
-    PyInterp_Dispatcher::Get()->Exec( new LoadReq( myInterp, this, files, loaded ) );
+    PyInterp_Dispatcher::Get()->Exec( new LoadReq( myInterp, this, files, url, loaded ) );
 
   return loaded;
 }
@@ -1899,9 +1952,9 @@ void PyModuleHelper::internalInitialize( CAM_Application* app )
           // parse the return value
           // it should be a map: {integer:integer}
           int aKey, aValue;
-          if( key && PyInt_Check( key ) && value && PyInt_Check( value ) ) {
-            aKey   = PyInt_AsLong( key );
-            aValue = PyInt_AsLong( value );
+          if( key && PyLong_Check( key ) && value && PyLong_Check( value ) ) {
+            aKey   = PyLong_AsLong( key );
+            aValue = PyLong_AsLong( value );
             myWindowsMap[ aKey ] = aValue;
           }
         }
@@ -1919,16 +1972,16 @@ void PyModuleHelper::internalInitialize( CAM_Application* app )
     else {
       // parse the return value
       // result can be one string...
-      if ( PyString_Check( res2 ) ) {
-        myViewMgrList.append( PyString_AsString( res2 ) );
+      if ( PyUnicode_Check( res2 ) ) {
+        myViewMgrList.append( PyUnicode_AsUTF8( res2 ) );
       }
       // ... or list of strings
       else if ( PyList_Check( res2 ) ) {
         int size = PyList_Size( res2 );
         for ( int i = 0; i < size; i++ ) {
           PyObject* value = PyList_GetItem( res2, i );
-          if( value && PyString_Check( value ) ) {
-            myViewMgrList.append( PyString_AsString( value ) );
+          if( value && PyUnicode_Check( value ) ) {
+            myViewMgrList.append( PyUnicode_AsUTF8( value ) );
           }
         }
       }
@@ -2205,6 +2258,43 @@ void PyModuleHelper::internalActionActivated( int id )
   }
 }
 
+/*!
+  \brief update selection from other views or modules
+  \internal
+
+  Performs the following actions:
+  - calls Python module's onSelectionpdated(entries) method
+
+  \param list of entries
+*/
+void PyModuleHelper::internalSelectionUpdated(const QStringList& entries)
+{
+  FuncMsg fmsg("--- PyModuleHelper::internalSelectionUpdated()");
+  MESSAGE("internalSelectionUpdated");
+
+  // Python interpreter should be initialized and Python module should be imported first
+  if (!myInterp || !myPyModule)
+    return; // Error
+
+  QStringList* theList = new QStringList(entries);
+
+#if SIP_VERSION < 0x040800
+  PyObjWrapper sipList(sipBuildResult(0, "M", theList, sipClass_QStringList));
+#else
+  PyObjWrapper sipList( sipBuildResult( 0, "D", theList, sipType_QStringList, NULL ) );
+#endif
+  if (PyObject_HasAttrString(myPyModule, (char*) "onSelectionUpdated"))
+    {
+      MESSAGE("call onSelectionUpdated");
+      PyObjWrapper res(PyObject_CallMethod(myPyModule, (char*) "onSelectionUpdated", (char*) "O", sipList.get()));
+
+      if (!res)
+        {
+          PyErr_Print();
+        }
+    }
+}
+
 /*!
   \brief Context popup menu handling callback function
   \internal
@@ -2415,8 +2505,9 @@ void PyModuleHelper::internalCloneView( SUIT_ViewWindow* view )
   \brief Module data saving callback function.
   \internal
   \param files output list of files where module stores data
+  \param url study URL
 */
-void PyModuleHelper::internalSave( QStringList& files )
+void PyModuleHelper::internalSave( QStringList& files, const QString& url )
 {
   FuncMsg fmsg( "--- PyModuleHelper::internalSave()" );
 
@@ -2428,17 +2519,24 @@ void PyModuleHelper::internalSave( QStringList& files )
 
   if ( PyObject_HasAttrString(myPyModule, (char*)"saveFiles") ) {
 
+    // try with two parameters (new syntax)
     PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"saveFiles",
-                                           (char*)"s", files.first().toLatin1().constData() ) );
-
+                                           (char*)"ss",
+                                           files.first().toLatin1().constData(),
+                                           url.toLatin1().constData() ) );
+    if ( !res )
+      // try with single parameter (old syntax)
+      res = PyObject_CallMethod( myPyModule, (char*)"saveFiles",
+                                 (char*)"s", files.first().toLatin1().constData() );
+    
     if ( !res ) {
       PyErr_Print();
     }
     else {
       // parse the return value
       // result can be one string...
-      if ( PyString_Check( res ) ) {
-        QString astr = PyString_AsString( res );
+      if ( PyUnicode_Check( res ) ) {
+        QString astr = PyUnicode_AsUTF8( res );
         files.append( astr );
       }
       //also result can be a list...
@@ -2446,8 +2544,8 @@ void PyModuleHelper::internalSave( QStringList& files )
         int size = PyList_Size( res );
         for ( int i = 0; i < size; i++ ) {
           PyObject* value = PyList_GetItem( res, i );
-          if ( value && PyString_Check( value ) ) {
-            files.append( PyString_AsString( value ) );
+          if ( value && PyUnicode_Check( value ) ) {
+            files.append( PyUnicode_AsUTF8( value ) );
           }
         }
       }
@@ -2459,9 +2557,10 @@ void PyModuleHelper::internalSave( QStringList& files )
   \brief Module data loading callback function.
   \internal
   \param files list of files where module data is stored
+  \param url study URL
   \param opened output success flag
 */
-void PyModuleHelper::internalLoad( const QStringList& files, bool& opened )
+void PyModuleHelper::internalLoad( const QStringList& files, const QString& url, bool& opened )
 {
   FuncMsg fmsg( "--- PyModuleHelper::internalLoad()" );
 
@@ -2478,13 +2577,22 @@ void PyModuleHelper::internalLoad( const QStringList& files, bool& opened )
   PyObjWrapper sipList( sipBuildResult( 0, "D", theList, sipType_QStringList, NULL ) );
 #endif
   if ( PyObject_HasAttrString(myPyModule , (char*)"openFiles") ) {
+
+    // try with two parameters (new syntax)
     PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"openFiles",
-                                           (char*)"O", sipList.get()));
-    if( !res || !PyBool_Check( res )) {
+                                           (char*)"Os", sipList.get(),
+                                           url.toLatin1().constData() ) );
+
+    if ( !res )
+      // try with single parameter (old syntax)
+      res = PyObject_CallMethod( myPyModule, (char*)"openFiles",
+                                 (char*)"O", sipList.get() );
+
+    if ( !res || !PyBool_Check( res ) ) {
       PyErr_Print();
       opened = false;
     }
-    else{
+    else {
       opened = PyObject_IsTrue( res );
     }
   }
@@ -2515,8 +2623,8 @@ void PyModuleHelper::internalDumpPython( QStringList& files )
     else {
       // parse the return value
       // result can be one string...
-      if ( PyString_Check( res ) ) {
-        QString astr = PyString_AsString( res );
+      if ( PyUnicode_Check( res ) ) {
+        QString astr = PyUnicode_AsUTF8( res );
         //SCRUTE(astr);
         files.append(astr);
       }
@@ -2525,8 +2633,8 @@ void PyModuleHelper::internalDumpPython( QStringList& files )
         int size = PyList_Size( res );
         for ( int i = 0; i < size; i++ ) {
           PyObject* value = PyList_GetItem( res, i );
-          if( value && PyString_Check( value ) ) {
-            files.append( PyString_AsString( value ) );
+          if( value && PyUnicode_Check( value ) ) {
+            files.append( PyUnicode_AsUTF8( value ) );
           }
         }
       }
@@ -2668,8 +2776,8 @@ QString PyModuleHelper::internalEngineIOR() const
       }
       else {
         // parse the return value, result chould be string
-        if ( PyString_Check( res ) ) {
-          ior = PyString_AsString( res );
+        if ( PyUnicode_Check( res ) ) {
+          ior = PyUnicode_AsUTF8( res );
         }
       }
     }