changeset 27599:ada24a1979c0

improve thread safety of qt_interpreter_events::get_named_icon * qt-interpreter-events.h, qt-interpreter-events.cc (qt_interpreter_events::get_named_icon_result): New data member. (qt_interpreter_events::get_named_icon_signal): New signal (qt_interpreter_events::get_named_icon_slot): New slot to access resource_manager in GUI thread. (qt_interpreter_events::get_named_icon): Emit signal, wait for result, and perform QIcon to uint8NDArray conversion in interpreter thread. (qt_interpreter_events::qt_interpreter_events): Connect new signal and slot.
author John W. Eaton <jwe@octave.org>
date Thu, 31 Oct 2019 10:39:43 -0400
parents cf9fbfa04dd1
children bb9aecedc167
files libgui/src/qt-interpreter-events.cc libgui/src/qt-interpreter-events.h
diffstat 2 files changed, 54 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/qt-interpreter-events.cc	Thu Oct 31 09:59:35 2019 -0400
+++ b/libgui/src/qt-interpreter-events.cc	Thu Oct 31 10:39:43 2019 -0400
@@ -117,6 +117,9 @@
 
     connect (this, SIGNAL (confirm_shutdown_signal (void)),
              this, SLOT (confirm_shutdown_octave (void)));
+
+    connect (this, SIGNAL (get_named_icon_signal (const QString&)),
+             this, SLOT (get_named_icon_slot (const QString&)));
   }
 
   std::list<std::string>
@@ -327,32 +330,58 @@
     return retval;
   }
 
-  uint8NDArray qt_interpreter_events::get_named_icon (const std::string& icon_name)
+  uint8NDArray qt_interpreter_events::get_named_icon (const std::string& name)
   {
-    uint8NDArray retval;
-    QIcon icon = resource_manager::icon (QString::fromStdString (icon_name));
-    if (! icon.isNull ())
+    QMutexLocker autolock (&m_mutex);
+
+    emit get_named_icon_signal (QString::fromStdString (name));
+
+    // Wait for result.
+    wait ();
+
+    uint8NDArray empty_img;
+
+    if (m_get_named_icon_result.isNull ())
+      return empty_img;
+
+    QImage img = m_get_named_icon_result.pixmap (QSize (32, 32)).toImage ();
+
+    if (img.format () != QImage::Format_ARGB32_Premultiplied)
+      return empty_img;
+
+    dim_vector dims (img.height (), img.width (), 4);
+
+    uint8NDArray retval (dims, 0);
+
+    uint8_t *bits = img.bits ();
+
+    for (int i = 0; i < img.height (); i++)
       {
-        QImage img = icon.pixmap (QSize (32, 32)).toImage ();
-
-        if (img.format () == QImage::Format_ARGB32_Premultiplied)
+        for (int j = 0; j < img.width (); j++)
           {
-            retval.resize (dim_vector (img.height (), img.width (), 4), 0);
-            uint8_t* bits = img.bits ();
-            for (int i = 0; i < img.height (); i++)
-              for (int j = 0; j < img.width (); j++)
-                {
-                  retval(i,j,2) = bits[0];
-                  retval(i,j,1) = bits[1];
-                  retval(i,j,0) = bits[2];
-                  retval(i,j,3) = bits[3];
-                  bits += 4;
-                }
+            retval(i,j,2) = bits[0];
+            retval(i,j,1) = bits[1];
+            retval(i,j,0) = bits[2];
+            retval(i,j,3) = bits[3];
+
+            bits += 4;
           }
       }
+
     return retval;
   }
 
+  void qt_interpreter_events::get_named_icon_slot (const QString& name)
+  {
+    lock ();
+
+    m_get_named_icon_result = resource_manager::icon (name);
+
+    unlock ();
+
+    wake_all ();
+  }
+
   std::string
   qt_interpreter_events::gui_preference (const std::string& key,
                                          const std::string& value)
--- a/libgui/src/qt-interpreter-events.h	Thu Oct 31 09:59:35 2019 -0400
+++ b/libgui/src/qt-interpreter-events.h	Thu Oct 31 10:39:43 2019 -0400
@@ -28,6 +28,7 @@
 #include <list>
 #include <string>
 
+#include <QIcon>
 #include <QList>
 #include <QMutex>
 #include <QObject>
@@ -180,6 +181,8 @@
 
     void confirm_shutdown_octave (void);
 
+    void get_named_icon_slot (const QString& name);
+
   signals:
 
     void copy_image_to_clipboard_signal (const QString& file, bool remove_file);
@@ -234,6 +237,8 @@
 
     void confirm_shutdown_signal (void);
 
+    void get_named_icon_signal (const QString& name);
+
   private:
 
     void insert_debugger_pointer (const std::string& file, int line);
@@ -244,6 +249,8 @@
 
     bool m_shutdown_confirm_result;
 
+    QIcon m_get_named_icon_result;
+
     QMutex m_mutex;
 
     QWaitCondition m_waitcondition;