# HG changeset patch
# User Pantxo Diribarne <pantxo.diribarne@gmail.com>
# Date 1590478926 -7200
#      Tue May 26 09:42:06 2020 +0200
# Node ID 219694886887dfd9f04284892f4ec809f201984d
# Parent  e11c8e1a91e258939e4b04c4fb1674cde4730c0c
Make sure Objects and their proxy are initialized synchronously (bug #55225)
  
* qt-graphics-toolkit.cc (qt_graphics_toolkit::qt_graphics_toolkit): use
  Qt::BlockingQueuedConnection to make sure the Object proxy "init" method
  has been called when we return.

* ObjectProxy.h (sendFinalize, sendPrint): remove unused signals.

* ObjectProxy.cc (ObjectProxy::ObjectProxy): Remove connections to slotPrint,
   and slotFinalize.
  (ObjectProxy::print): Use QMetaObject::invokeMethod with a
   Qt::BlockingQueuedConnection to execute slotPrint. Raise an error if either
   the GUI Object is not valid or invokeMethod failed.
  (ObjectProxy::finalize): Raise an error if either the GUI Object is not valid
   or invokeMethod failed.
  (ObjectProxy::get_pixels): Raise an error if the GUI Object is not valid.
  (ObjectProxy::setObject): Only call finalize with a valid GUI Object. 

diff -r e11c8e1a91e2 -r 219694886887 libgui/graphics/ObjectProxy.cc
--- a/libgui/graphics/ObjectProxy.cc	Mon May 25 21:07:23 2020 +0200
+++ b/libgui/graphics/ObjectProxy.cc	Tue May 26 09:42:06 2020 +0200
@@ -55,14 +55,10 @@
           {
             disconnect (this, SIGNAL (sendUpdate (int)),
                         m_object, SLOT (slotUpdate (int)));
-            disconnect (this, SIGNAL (sendFinalize (void)),
-                        m_object, SLOT (slotFinalize (void)));
             disconnect (this, SIGNAL (sendRedraw (void)),
                         m_object, SLOT (slotRedraw (void)));
             disconnect (this, SIGNAL (sendShow (void)),
                         m_object, SLOT (slotShow (void)));
-            disconnect (this, SIGNAL (sendPrint (const QString&, const QString&)),
-                        m_object, SLOT (slotPrint (const QString&, const QString&)));
           }
 
         m_object = obj;
@@ -71,15 +67,10 @@
           {
             connect (this, SIGNAL (sendUpdate (int)),
                      m_object, SLOT (slotUpdate (int)));
-            connect (this, SIGNAL (sendFinalize (void)),
-                     m_object, SLOT (slotFinalize (void)));
             connect (this, SIGNAL (sendRedraw (void)),
                      m_object, SLOT (slotRedraw (void)));
             connect (this, SIGNAL (sendShow (void)),
                      m_object, SLOT (slotShow (void)));
-            connect (this, SIGNAL (sendPrint (const QString&, const QString&)),
-                     m_object, SLOT (slotPrint (const QString&, const QString&)),
-                     Qt::BlockingQueuedConnection);
           }
       }
   }
@@ -87,7 +78,10 @@
   void
   ObjectProxy::setObject (Object *obj)
   {
-    finalize ();
+    // Eventually destroy previous Object
+    if (m_object)
+      finalize ();
+
     init (obj);
   }
 
@@ -101,14 +95,15 @@
   ObjectProxy::finalize (void)
   {
     if (! m_object)
-      return;
+      error ("ObjectProxy::finalize: invalid GUI Object");
 
     Qt::ConnectionType t = Qt::BlockingQueuedConnection;
 
     if (QThread::currentThread () == QCoreApplication::instance ()->thread ())
       t = Qt::DirectConnection;
 
-    QMetaObject::invokeMethod (m_object, "slotFinalize", t);
+    if (! QMetaObject::invokeMethod (m_object, "slotFinalize", t))
+      error ("ObjectProxy::finalize: unable to delete GUI Object");
   }
 
   void
@@ -126,12 +121,26 @@
   void
   ObjectProxy::print (const QString& file_cmd, const QString& term)
   {
-    emit sendPrint (file_cmd, term);
+    if (! m_object)
+      error ("ObjectProxy::print: invalid GUI Object");
+
+    Qt::ConnectionType t = Qt::BlockingQueuedConnection;
+
+    if (QThread::currentThread () == QCoreApplication::instance ()->thread ())
+      t = Qt::DirectConnection;
+
+    if (! QMetaObject::invokeMethod (m_object, "slotPrint", t,
+                                     Q_ARG (QString, file_cmd),
+                                     Q_ARG (QString, term)))
+      error ("ObjectProxy::print: unable to print figure");
   }
 
   uint8NDArray
   ObjectProxy::get_pixels (void)
   {
+    if (! m_object)
+      error ("ObjectProxy::finalize: invalid GUI Object");
+
     uint8NDArray retval;
 
     // The ObjectProxy is generally ran from the interpreter thread
diff -r e11c8e1a91e2 -r 219694886887 libgui/graphics/ObjectProxy.h
--- a/libgui/graphics/ObjectProxy.h	Mon May 25 21:07:23 2020 +0200
+++ b/libgui/graphics/ObjectProxy.h	Tue May 26 09:42:06 2020 +0200
@@ -56,10 +56,8 @@
 
   signals:
     void sendUpdate (int pId);
-    void sendFinalize (void);
     void sendRedraw (void);
     void sendShow (void);
-    void sendPrint (const QString& file_cmd, const QString& term);
 
   private:
     void init (Object *obj);
diff -r e11c8e1a91e2 -r 219694886887 libgui/graphics/qt-graphics-toolkit.cc
--- a/libgui/graphics/qt-graphics-toolkit.cc	Mon May 25 21:07:23 2020 +0200
+++ b/libgui/graphics/qt-graphics-toolkit.cc	Tue May 26 09:42:06 2020 +0200
@@ -107,9 +107,14 @@
     // cross from the interpreter thread (where requests to create
     // graphics object are initiated) to the GUI application thread
     // (where they are actually created and displayed).
+    // We need to make sure the GUI Object and its proxy are properly
+    // created before the initialize method returns, so we use a
+    // BlockingQueuedConnection. After the signal is emitted, the interpreter
+    // thread is locked until the slot has returned.
 
     connect (this, SIGNAL (create_object_signal (double)),
-             this, SLOT (create_object (double)));
+             this, SLOT (create_object (double)),
+             Qt::BlockingQueuedConnection);
   }
 
   bool
