changeset 27317:718116e9c7d3

rename Backend to qt_graphics_toolkit * qt-graphics-toolkit.h, qt-graphics-toolkit.cc: Rename from Backend.h and Backend.cc. Change all uses. (class qt_graphics_toolkit): Rename from Backend. Change all uses. * libgui/graphics/module.mk: Update.
author John W. Eaton <jwe@octave.org>
date Fri, 02 Aug 2019 12:18:48 -0500
parents 22265a75be74
children ae53e56e16f2
files libgui/graphics/Backend.cc libgui/graphics/Backend.h libgui/graphics/ButtonGroup.cc libgui/graphics/Canvas.cc libgui/graphics/ContextMenu.cc libgui/graphics/Object.cc libgui/graphics/Object.h libgui/graphics/ObjectFactory.cc libgui/graphics/ObjectFactory.h libgui/graphics/QtHandlesUtils.cc libgui/graphics/__init_qt__.cc libgui/graphics/module.mk libgui/graphics/qt-graphics-toolkit.cc libgui/graphics/qt-graphics-toolkit.h
diffstat 14 files changed, 474 insertions(+), 473 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/graphics/Backend.cc	Tue Jul 30 15:00:54 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,338 +0,0 @@
-/*
-
-Copyright (C) 2011-2019 Michael Goffioul
-
-This file is part of Octave.
-
-Octave is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Octave is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include <cstdint>
-
-#include <QApplication>
-#include <QFontMetrics>
-#include <QThread>
-
-#include "Backend.h"
-#include "Logger.h"
-#include "Object.h"
-#include "ObjectFactory.h"
-#include "ObjectProxy.h"
-#include "QtHandlesUtils.h"
-
-#include "event-manager.h"
-#include "interpreter.h"
-
-//#if INTPTR_MAX == INT32_MAX
-//# define OCTAVE_PTR_TYPE octave_uint32
-//# define OCTAVE_INTPTR_TYPE uint32_t
-//# define OCTAVE_PTR_SCALAR uint32_scalar_value
-//#else
-# define OCTAVE_PTR_TYPE octave_uint64
-# define OCTAVE_INTPTR_TYPE uint64_t
-# define OCTAVE_PTR_SCALAR uint64_scalar_value
-//#endif
-
-namespace QtHandles
-{
-
-  static std::string
-  toolkitObjectProperty (const graphics_object& go)
-  {
-    if (go.isa ("figure"))
-      return "__plot_stream__";
-    else if (go.isa ("uicontrol")
-             || go.isa ("uipanel")
-             || go.isa ("uibuttongroup")
-             || go.isa ("uimenu")
-             || go.isa ("uicontextmenu")
-             || go.isa ("uitable")
-             || go.isa ("uitoolbar")
-             || go.isa ("uipushtool")
-             || go.isa ("uitoggletool"))
-      return "__object__";
-    else
-      qCritical ("QtHandles::Backend: no __object__ property known for object "
-                 "of type %s", go.type ().c_str ());
-
-    return "";
-  }
-
-  Backend::Backend (octave::interpreter& interp)
-    : QObject (), base_graphics_toolkit ("qt"), m_interpreter (interp),
-      m_factory (new ObjectFactory ())
-  {
-    if (QThread::currentThread () != QApplication::instance ()->thread ())
-      m_factory->moveToThread (QApplication::instance ()->thread ());
-
-    connect (this, SIGNAL (createObject (Backend *, double)),
-             m_factory, SLOT (createObject (Backend *, double)),
-             Qt::BlockingQueuedConnection);
-  }
-
-  Backend::~Backend (void)
-  {
-    delete m_factory;
-  }
-
-  bool
-  Backend::initialize (const graphics_object& go)
-  {
-    if (go.isa ("figure")
-        || go.isa ("uicontrol")
-        || go.isa ("uipanel")
-        || go.isa ("uibuttongroup")
-        || go.isa ("uimenu")
-        || go.isa ("uicontextmenu")
-        || go.isa ("uitable")
-        || go.isa ("uitoolbar")
-        || go.isa ("uipushtool")
-        || go.isa ("uitoggletool"))
-      {
-        // FIXME: We need to unlock the mutex here but we have no way to know if
-        // if it was previously locked by this thread, and thus if we should
-        // re-lock it.
-        gh_manager::unlock ();
-
-        Logger::debug ("Backend::initialize %s from thread %08x",
-                       go.type ().c_str (), QThread::currentThreadId ());
-
-        ObjectProxy *proxy = new ObjectProxy ();
-        graphics_object gObj (go);
-
-        OCTAVE_PTR_TYPE tmp (reinterpret_cast<OCTAVE_INTPTR_TYPE> (proxy));
-        gObj.get_properties ().set (toolkitObjectProperty (go), tmp);
-
-        emit createObject (this, go.get_handle ().value ());
-
-        return true;
-      }
-
-    return false;
-  }
-
-  void
-  Backend::update (const graphics_object& go, int pId)
-  {
-    // Rule out obvious properties we want to ignore.
-    if (pId == figure::properties::ID___PLOT_STREAM__
-        || pId == uicontrol::properties::ID___OBJECT__
-        || pId == uipanel::properties::ID___OBJECT__
-        || pId == uibuttongroup::properties::ID___OBJECT__
-        || pId == uimenu::properties::ID___OBJECT__
-        || pId == uicontextmenu::properties::ID___OBJECT__
-        || pId == uitable::properties::ID___OBJECT__
-        || pId == uitoolbar::properties::ID___OBJECT__
-        || pId == uipushtool::properties::ID___OBJECT__
-        || pId == uitoggletool::properties::ID___OBJECT__
-        || pId == base_properties::ID___MODIFIED__)
-      return;
-
-    Logger::debug ("Backend::update %s(%d) from thread %08x",
-                   go.type ().c_str (), pId, QThread::currentThreadId ());
-
-    ObjectProxy *proxy = toolkitObjectProxy (go);
-
-    if (proxy)
-      {
-        if (go.isa ("uicontrol")
-            && pId == uicontrol::properties::ID_STYLE)
-          {
-            // Special case: we need to recreate the control widget
-            // associated with the octave graphics_object
-
-            finalize (go);
-            initialize (go);
-          }
-        else
-          proxy->update (pId);
-      }
-  }
-
-  void
-  Backend::finalize (const graphics_object& go)
-  {
-    // FIXME: We need to unlock the mutex here but we have no way to know if
-    // if it was previously locked by this thread, and thus if we should
-    // re-lock it.
-    gh_manager::unlock ();
-
-    Logger::debug ("Backend::finalize %s from thread %08x",
-                   go.type ().c_str (), QThread::currentThreadId ());
-
-    ObjectProxy *proxy = toolkitObjectProxy (go);
-
-    if (proxy)
-      {
-        proxy->finalize ();
-        delete proxy;
-
-        graphics_object gObj (go);
-
-        gObj.get_properties ().set (toolkitObjectProperty (go), Matrix ());
-      }
-  }
-
-  void
-  Backend::redraw_figure (const graphics_object& go) const
-  {
-    if (go.get_properties ().is_visible ())
-      {
-        ObjectProxy *proxy = toolkitObjectProxy (go);
-
-        if (proxy)
-          proxy->redraw ();
-      }
-  }
-
-  void
-  Backend::show_figure (const graphics_object& go) const
-  {
-    if (go.get_properties ().is_visible ())
-      {
-        ObjectProxy *proxy = toolkitObjectProxy (go);
-
-        if (proxy)
-          proxy->show ();
-      }
-  }
-
-  void
-  Backend::print_figure (const graphics_object& go,
-                         const std::string& term,
-                         const std::string& file_cmd,
-                         const std::string& /*debug_file*/) const
-  {
-    ObjectProxy *proxy = toolkitObjectProxy (go);
-
-    if (proxy)
-      proxy->print (QString::fromStdString (file_cmd),
-                    QString::fromStdString (term));
-  }
-
-  uint8NDArray
-  Backend::get_pixels (const graphics_object& go) const
-  {
-    uint8NDArray retval;
-
-    if (go.isa ("figure"))
-      {
-        ObjectProxy *proxy = toolkitObjectProxy (go);
-
-        if (proxy)
-          retval = proxy->get_pixels ();
-      }
-
-    return retval;
-  }
-
-  Matrix
-  Backend::get_text_extent (const graphics_object& go) const
-  {
-    Matrix ext (1, 4, 0.0);
-
-    if (go.isa ("uicontrol"))
-      {
-        octave_value str = go.get ("string");
-        if (! str.isempty ())
-          {
-            const uicontrol::properties& up =
-              dynamic_cast<const uicontrol::properties&> (go.get_properties ());
-            Matrix bb = up.get_boundingbox (false);
-            QFont font = Utils::computeFont<uicontrol> (up, bb(3));
-            QFontMetrics fm (font);
-
-            QString s;
-            QSize sz;
-
-            if (str.is_string ())
-              {
-                s = QString::fromStdString (str.string_value ());
-                sz = fm.size (Qt::TextSingleLine, s);
-                ext(2) = sz.width ();
-                ext(3) = sz.height ();
-              }
-            else if (str.iscellstr ())
-              {
-                string_vector sv = str.string_vector_value ();
-                double wd = 0.0;
-                double hg = 0.0;
-                for (octave_idx_type ii = 0; ii < sv.numel (); ii++)
-                  {
-                    s = QString::fromStdString (sv(ii));
-                    sz = fm.size (Qt::TextSingleLine, s);
-                    wd = std::max (wd, static_cast<double> (sz.width ()));
-                    hg = std::max (hg, static_cast<double> (sz.height ()));
-                  }
-
-                ext(2) = wd;
-                // FIXME: Find a better way to determine the height of e.g.
-                // listbox uicontrol objects
-                ext(3) = hg * sv.numel ();
-              }
-          }
-      }
-
-    return ext;
-  }
-
-  Object*
-  Backend::toolkitObject (const graphics_object& go)
-  {
-    ObjectProxy *proxy = toolkitObjectProxy (go);
-
-    if (proxy)
-      return proxy->object ();
-
-    return nullptr;
-  }
-
-  ObjectProxy*
-  Backend::toolkitObjectProxy (const graphics_object& go)
-  {
-    if (go)
-      {
-        octave_value ov = go.get (toolkitObjectProperty (go));
-
-        if (ov.is_defined () && ! ov.isempty ())
-          {
-            OCTAVE_INTPTR_TYPE ptr = ov.OCTAVE_PTR_SCALAR ().value ();
-
-            return reinterpret_cast<ObjectProxy *> (ptr);
-          }
-      }
-
-    return nullptr;
-  }
-
-  void Backend::interpreter_event (const octave::fcn_callback& fcn)
-  {
-    octave::event_manager& evmgr = m_interpreter.get_event_manager ();
-
-    evmgr.post_event (fcn);
-  }
-
-  void Backend::interpreter_event (const octave::meth_callback& meth)
-  {
-    octave::event_manager& evmgr = m_interpreter.get_event_manager ();
-
-    evmgr.post_event (meth);
-  }
-};
--- a/libgui/graphics/Backend.h	Tue Jul 30 15:00:54 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
-
-Copyright (C) 2011-2019 Michael Goffioul
-
-This file is part of Octave.
-
-Octave is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Octave is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if ! defined (octave_Backend_h)
-#define octave_Backend_h 1
-
-#include <QObject>
-
-#include "event-manager.h"
-#include "graphics.h"
-
-namespace octave
-{
-  class interpreter;
-}
-
-namespace QtHandles
-{
-  class Object;
-  class ObjectFactory;
-  class ObjectProxy;
-
-  class Backend :
-  public QObject,
-  public base_graphics_toolkit
-  {
-    Q_OBJECT
-
-  public:
-
-    Backend (octave::interpreter& interp);
-
-    ~Backend (void);
-
-    bool is_valid (void) const { return true; }
-
-    void redraw_figure (const graphics_object& h) const;
-
-    void show_figure (const graphics_object& h) const;
-
-    void update (const graphics_object& obj, int pId);
-
-    bool initialize (const graphics_object& obj);
-
-    void finalize (const graphics_object& obj);
-
-    void print_figure (const graphics_object& go,
-                       const std::string& term,
-                       const std::string& file_cmd,
-                       const std::string& /*debug_file*/) const;
-
-    uint8NDArray get_pixels (const graphics_object& go) const;
-
-    Matrix get_text_extent (const graphics_object& go) const;
-
-    static Object * toolkitObject (const graphics_object& go);
-
-    static ObjectProxy * toolkitObjectProxy (const graphics_object& go);
-
-  signals:
-    void createObject (Backend *, double handle);
-
-  public slots:
-
-    void interpreter_event (const octave::fcn_callback& fcn);
-    void interpreter_event (const octave::meth_callback& meth);
-
-  private:
-
-    octave::interpreter& m_interpreter;
-
-    ObjectFactory *m_factory;
-  };
-
-}
-
-#endif
--- a/libgui/graphics/ButtonGroup.cc	Tue Jul 30 15:00:54 2019 -0500
+++ b/libgui/graphics/ButtonGroup.cc	Fri Aug 02 12:18:48 2019 -0500
@@ -39,8 +39,8 @@
 #include "ButtonGroup.h"
 #include "ToggleButtonControl.h"
 #include "RadioButtonControl.h"
-#include "Backend.h"
 #include "QtHandlesUtils.h"
+#include "qt-graphics-toolkit.h"
 
 #include "ov-struct.h"
 
@@ -355,7 +355,7 @@
           graphics_handle h = pp.get_selectedobject ();
           gh_manager::auto_lock lock;
           graphics_object go = gh_manager::get_object (h);
-          Object *selectedObject = Backend::toolkitObject (go);
+          Object *selectedObject = qt_graphics_toolkit::toolkitObject (go);
           ToggleButtonControl *toggle = static_cast<ToggleButtonControl *>
                                         (selectedObject);
           RadioButtonControl *radio = static_cast<RadioButtonControl *>(selectedObject);
--- a/libgui/graphics/Canvas.cc	Tue Jul 30 15:00:54 2019 -0500
+++ b/libgui/graphics/Canvas.cc	Fri Aug 02 12:18:48 2019 -0500
@@ -33,11 +33,11 @@
 #include <QWheelEvent>
 #include <QRectF>
 
-#include "Backend.h"
 #include "Canvas.h"
 #include "ContextMenu.h"
 #include "GLCanvas.h"
 #include "QtHandlesUtils.h"
+#include "qt-graphics-toolkit.h"
 
 #include "annotation-dialog.h"
 
@@ -533,7 +533,7 @@
             // FIXME: should we use signal/slot mechanism instead of
             //        directly calling parent fig methods
             Figure *fig =
-              dynamic_cast<Figure *> (Backend::toolkitObject (figObj));
+              dynamic_cast<Figure *> (qt_graphics_toolkit::toolkitObject (figObj));
             axes::properties& ap = Utils::properties<axes> (axesObj);
 
             if (fig)
@@ -631,7 +631,7 @@
           Utils::properties<figure> (figObj)
             .set_currentaxes (axesObj.get_handle ().as_octave_value ());
 
-        Figure *fig = dynamic_cast<Figure *> (Backend::toolkitObject (figObj));
+        Figure *fig = dynamic_cast<Figure *> (qt_graphics_toolkit::toolkitObject (figObj));
 
         MouseMode newMouseMode = NoMode;
 
@@ -928,7 +928,7 @@
           {
             MouseMode newMouseMode = NoMode;
 
-            Figure *fig = dynamic_cast<Figure *> (Backend::toolkitObject (figObj));
+            Figure *fig = dynamic_cast<Figure *> (qt_graphics_toolkit::toolkitObject (figObj));
 
             if (fig)
               newMouseMode = fig->mouseMode ();
--- a/libgui/graphics/ContextMenu.cc	Tue Jul 30 15:00:54 2019 -0500
+++ b/libgui/graphics/ContextMenu.cc	Fri Aug 02 12:18:48 2019 -0500
@@ -26,9 +26,9 @@
 
 #include <QMenu>
 
-#include "Backend.h"
 #include "ContextMenu.h"
 #include "QtHandlesUtils.h"
+#include "qt-graphics-toolkit.h"
 
 namespace QtHandles
 {
@@ -122,7 +122,7 @@
         if (go.valid_object ())
           {
             ContextMenu *cMenu =
-              dynamic_cast<ContextMenu *> (Backend::toolkitObject (go));
+              dynamic_cast<ContextMenu *> (qt_graphics_toolkit::toolkitObject (go));
 
             if (cMenu)
               {
--- a/libgui/graphics/Object.cc	Tue Jul 30 15:00:54 2019 -0500
+++ b/libgui/graphics/Object.cc	Fri Aug 02 12:18:48 2019 -0500
@@ -27,9 +27,9 @@
 #include <QString>
 #include <QVariant>
 
-#include "Backend.h"
 #include "Object.h"
 #include "QtHandlesUtils.h"
+#include "qt-graphics-toolkit.h"
 
 namespace QtHandles
 {
@@ -179,7 +179,7 @@
   {
     gh_manager::auto_lock lock;
 
-    Object *parent = Backend::toolkitObject
+    Object *parent = qt_graphics_toolkit::toolkitObject
                      (gh_manager::get_object (go.get_parent ()));
 
     return parent;
--- a/libgui/graphics/Object.h	Tue Jul 30 15:00:54 2019 -0500
+++ b/libgui/graphics/Object.h	Fri Aug 02 12:18:48 2019 -0500
@@ -108,11 +108,12 @@
 
     // Store the graphics object directly so that it will exist when
     // we need it.  Previously, it was possible for the graphics
-    // backend to get a handle to a figure, then have the interpreter
-    // thread delete the corresponding object before the backend (GUI)
-    // thread had a chance to display it.  It should be OK to store
-    // this object and use it in both threads (graphics_object uses a
-    // std::shared_ptr) provided that we protect access with mutex locks.
+    // toolkit to get a handle to a figure, then have the interpreter
+    // thread delete the corresponding object before the graphics
+    // toolkit (GUI) thread had a chance to display it.  It should be OK
+    // to store this object and use it in both threads (graphics_object
+    // uses a std::shared_ptr) provided that we protect access with
+    // mutex locks.
     graphics_object m_go;
 
     // Handle to the graphics object.  This may be redundant now.
--- a/libgui/graphics/ObjectFactory.cc	Tue Jul 30 15:00:54 2019 -0500
+++ b/libgui/graphics/ObjectFactory.cc	Fri Aug 02 12:18:48 2019 -0500
@@ -30,7 +30,6 @@
 #include "event-manager.h"
 #include "graphics.h"
 
-#include "Backend.h"
 #include "ButtonGroup.h"
 #include "CheckBoxControl.h"
 #include "ContextMenu.h"
@@ -53,11 +52,12 @@
 #include "ToggleTool.h"
 #include "ToolBar.h"
 #include "QtHandlesUtils.h"
+#include "qt-graphics-toolkit.h"
 
 namespace QtHandles
 {
   void
-  ObjectFactory::createObject (Backend *backend, double handle)
+  ObjectFactory::createObject (qt_graphics_toolkit *qt_gtk, double handle)
   {
     gh_manager::auto_lock lock;
 
@@ -69,7 +69,7 @@
           qWarning ("ObjectFactory::createObject: object is being deleted");
         else
           {
-            ObjectProxy *proxy = Backend::toolkitObjectProxy (go);
+            ObjectProxy *proxy = qt_graphics_toolkit::toolkitObjectProxy (go);
 
             if (proxy)
               {
@@ -131,12 +131,12 @@
 
                     connect (obj,
                              SIGNAL (interpreter_event (const octave::fcn_callback&)),
-                             backend,
+                             qt_gtk,
                              SLOT (interpreter_event (const octave::fcn_callback&)));
 
                     connect (obj,
                              SIGNAL (interpreter_event (const octave::meth_callback&)),
-                             backend,
+                             qt_gtk,
                              SLOT (interpreter_event (const octave::meth_callback&)));
                   }
               }
--- a/libgui/graphics/ObjectFactory.h	Tue Jul 30 15:00:54 2019 -0500
+++ b/libgui/graphics/ObjectFactory.h	Fri Aug 02 12:18:48 2019 -0500
@@ -29,7 +29,7 @@
 
 namespace QtHandles
 {
-  class Backend;
+  class qt_graphics_toolkit;
   class Object;
 
   class ObjectFactory : public QObject
@@ -42,7 +42,7 @@
 
   public slots:
 
-    void createObject (Backend *, double handle);
+    void createObject (qt_graphics_toolkit *, double handle);
   };
 
 };
--- a/libgui/graphics/QtHandlesUtils.cc	Tue Jul 30 15:00:54 2019 -0500
+++ b/libgui/graphics/QtHandlesUtils.cc	Fri Aug 02 12:18:48 2019 -0500
@@ -33,11 +33,11 @@
 #include "ov.h"
 #include "graphics.h"
 
-#include "Backend.h"
 #include "Container.h"
 #include "KeyMap.h"
 #include "Object.h"
 #include "QtHandlesUtils.h"
+#include "qt-graphics-toolkit.h"
 
 #include "oct-string.h"
 
@@ -208,7 +208,7 @@
     Matrix
     figureCurrentPoint (const graphics_object& fig, QMouseEvent *event)
     {
-      Object *tkFig = Backend::toolkitObject (fig);
+      Object *tkFig = qt_graphics_toolkit::toolkitObject (fig);
 
       if (tkFig)
         {
@@ -229,7 +229,7 @@
     Matrix
     figureCurrentPoint (const graphics_object& fig)
     {
-      Object *tkFig = Backend::toolkitObject (fig);
+      Object *tkFig = qt_graphics_toolkit::toolkitObject (fig);
 
       if (tkFig)
         {
--- a/libgui/graphics/__init_qt__.cc	Tue Jul 30 15:00:54 2019 -0500
+++ b/libgui/graphics/__init_qt__.cc	Fri Aug 02 12:18:48 2019 -0500
@@ -37,7 +37,7 @@
 #include "interpreter.h"
 #include "symtab.h"
 
-#include "Backend.h"
+#include "qt-graphics-toolkit.h"
 #include "QtHandlesUtils.h"
 #include "__init_qt__.h"
 
@@ -65,7 +65,7 @@
 
             octave::gtk_manager& gtk_mgr = interp.get_gtk_manager ();
 
-            graphics_toolkit tk (new Backend (interp));
+            graphics_toolkit tk (new qt_graphics_toolkit (interp));
             gtk_mgr.load_toolkit (tk);
 
             octave::interpreter::add_atexit_function ("__shutdown_qt__");
--- a/libgui/graphics/module.mk	Tue Jul 30 15:00:54 2019 -0500
+++ b/libgui/graphics/module.mk	Fri Aug 02 12:18:48 2019 -0500
@@ -3,8 +3,6 @@
 LIBOCTGUI_GRAPHICS_LIB = %reldir%/__init_qt__.la
 
 OCTAVE_GUI_GRAPHICS_MOC = \
-  %reldir%/moc-annotation-dialog.cc \
-  %reldir%/moc-Backend.cc \
   %reldir%/moc-ButtonControl.cc \
   %reldir%/moc-ButtonGroup.cc \
   %reldir%/moc-Canvas.cc \
@@ -21,10 +19,12 @@
   %reldir%/moc-PopupMenuControl.cc \
   %reldir%/moc-PushTool.cc \
   %reldir%/moc-SliderControl.cc \
+  %reldir%/moc-Table.cc \
   %reldir%/moc-TextEdit.cc \
-  %reldir%/moc-Table.cc \
   %reldir%/moc-ToggleTool.cc \
-  %reldir%/moc-ToolBar.cc
+  %reldir%/moc-ToolBar.cc \
+  %reldir%/moc-annotation-dialog.cc \
+  %reldir%/moc-qt-graphics-toolkit.cc
 
 $(OCTAVE_GUI_GRAPHICS_MOC): | %reldir%/$(octave_dirstamp)
 
@@ -44,9 +44,6 @@
 BUILT_SOURCES += $(__init_qt___UI_H)
 
 noinst_HEADERS += \
-  %reldir%/__init_qt__.h \
-  %reldir%/annotation-dialog.h \
-  %reldir%/Backend.h \
   %reldir%/BaseControl.h \
   %reldir%/ButtonControl.h \
   %reldir%/ButtonGroup.h \
@@ -57,8 +54,8 @@
   %reldir%/EditControl.h \
   %reldir%/Figure.h \
   %reldir%/FigureWindow.h \
+  %reldir%/GLCanvas.h \
   %reldir%/GenericEventNotify.h \
-  %reldir%/GLCanvas.h \
   %reldir%/KeyMap.h \
   %reldir%/ListBoxControl.h \
   %reldir%/Logger.h \
@@ -81,14 +78,14 @@
   %reldir%/ToggleTool.h \
   %reldir%/ToolBar.h \
   %reldir%/ToolBarButton.h \
+  %reldir%/__init_qt__.h \
+  %reldir%/annotation-dialog.h \
   %reldir%/gl-select.h \
   %reldir%/qopengl-functions.h \
+  %reldir%/qt-graphics-toolkit.h \
   $(TEMPLATE_SRC)
 
 %canon_reldir%___init_qt___la_SOURCES = \
-  %reldir%/__init_qt__.cc \
-  %reldir%/annotation-dialog.cc \
-  %reldir%/Backend.cc \
   %reldir%/BaseControl.cc \
   %reldir%/ButtonControl.cc \
   %reldir%/ButtonGroup.cc \
@@ -120,7 +117,10 @@
   %reldir%/ToggleButtonControl.cc \
   %reldir%/ToggleTool.cc \
   %reldir%/ToolBar.cc \
-  %reldir%/gl-select.cc
+  %reldir%/__init_qt__.cc \
+  %reldir%/annotation-dialog.cc \
+  %reldir%/gl-select.cc \
+  %reldir%/qt-graphics-toolkit.cc
 
 TEMPLATE_SRC = \
   %reldir%/ToolBarButton.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/graphics/qt-graphics-toolkit.cc	Fri Aug 02 12:18:48 2019 -0500
@@ -0,0 +1,340 @@
+/*
+
+Copyright (C) 2011-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <cstdint>
+
+#include <QApplication>
+#include <QFontMetrics>
+#include <QThread>
+
+#include "Logger.h"
+#include "Object.h"
+#include "ObjectFactory.h"
+#include "ObjectProxy.h"
+#include "QtHandlesUtils.h"
+#include "qt-graphics-toolkit.h"
+
+#include "event-manager.h"
+#include "interpreter.h"
+
+//#if INTPTR_MAX == INT32_MAX
+//# define OCTAVE_PTR_TYPE octave_uint32
+//# define OCTAVE_INTPTR_TYPE uint32_t
+//# define OCTAVE_PTR_SCALAR uint32_scalar_value
+//#else
+# define OCTAVE_PTR_TYPE octave_uint64
+# define OCTAVE_INTPTR_TYPE uint64_t
+# define OCTAVE_PTR_SCALAR uint64_scalar_value
+//#endif
+
+namespace QtHandles
+{
+
+  static std::string
+  toolkitObjectProperty (const graphics_object& go)
+  {
+    if (go.isa ("figure"))
+      return "__plot_stream__";
+    else if (go.isa ("uicontrol")
+             || go.isa ("uipanel")
+             || go.isa ("uibuttongroup")
+             || go.isa ("uimenu")
+             || go.isa ("uicontextmenu")
+             || go.isa ("uitable")
+             || go.isa ("uitoolbar")
+             || go.isa ("uipushtool")
+             || go.isa ("uitoggletool"))
+      return "__object__";
+    else
+      qCritical ("QtHandles::qt_graphics_toolkit: no __object__ property known for object "
+                 "of type %s", go.type ().c_str ());
+
+    return "";
+  }
+
+  qt_graphics_toolkit::qt_graphics_toolkit (octave::interpreter& interp)
+    : QObject (), base_graphics_toolkit ("qt"), m_interpreter (interp),
+      m_factory (new ObjectFactory ())
+  {
+    if (QThread::currentThread () != QApplication::instance ()->thread ())
+      m_factory->moveToThread (QApplication::instance ()->thread ());
+
+    connect (this, SIGNAL (createObject (qt_graphics_toolkit *, double)),
+             m_factory, SLOT (createObject (qt_graphics_toolkit *, double)),
+             Qt::BlockingQueuedConnection);
+  }
+
+  qt_graphics_toolkit::~qt_graphics_toolkit (void)
+  {
+    delete m_factory;
+  }
+
+  bool
+  qt_graphics_toolkit::initialize (const graphics_object& go)
+  {
+    if (go.isa ("figure")
+        || go.isa ("uicontrol")
+        || go.isa ("uipanel")
+        || go.isa ("uibuttongroup")
+        || go.isa ("uimenu")
+        || go.isa ("uicontextmenu")
+        || go.isa ("uitable")
+        || go.isa ("uitoolbar")
+        || go.isa ("uipushtool")
+        || go.isa ("uitoggletool"))
+      {
+        // FIXME: We need to unlock the mutex here but we have no way to know if
+        // if it was previously locked by this thread, and thus if we should
+        // re-lock it.
+        gh_manager::unlock ();
+
+        Logger::debug ("qt_graphics_toolkit::initialize %s from thread %08x",
+                       go.type ().c_str (), QThread::currentThreadId ());
+
+        ObjectProxy *proxy = new ObjectProxy ();
+        graphics_object gObj (go);
+
+        OCTAVE_PTR_TYPE tmp (reinterpret_cast<OCTAVE_INTPTR_TYPE> (proxy));
+        gObj.get_properties ().set (toolkitObjectProperty (go), tmp);
+
+        emit createObject (this, go.get_handle ().value ());
+
+        return true;
+      }
+
+    return false;
+  }
+
+  void
+  qt_graphics_toolkit::update (const graphics_object& go, int pId)
+  {
+    // Rule out obvious properties we want to ignore.
+    if (pId == figure::properties::ID___PLOT_STREAM__
+        || pId == uicontrol::properties::ID___OBJECT__
+        || pId == uipanel::properties::ID___OBJECT__
+        || pId == uibuttongroup::properties::ID___OBJECT__
+        || pId == uimenu::properties::ID___OBJECT__
+        || pId == uicontextmenu::properties::ID___OBJECT__
+        || pId == uitable::properties::ID___OBJECT__
+        || pId == uitoolbar::properties::ID___OBJECT__
+        || pId == uipushtool::properties::ID___OBJECT__
+        || pId == uitoggletool::properties::ID___OBJECT__
+        || pId == base_properties::ID___MODIFIED__)
+      return;
+
+    Logger::debug ("qt_graphics_toolkit::update %s(%d) from thread %08x",
+                   go.type ().c_str (), pId, QThread::currentThreadId ());
+
+    ObjectProxy *proxy = toolkitObjectProxy (go);
+
+    if (proxy)
+      {
+        if (go.isa ("uicontrol")
+            && pId == uicontrol::properties::ID_STYLE)
+          {
+            // Special case: we need to recreate the control widget
+            // associated with the octave graphics_object
+
+            finalize (go);
+            initialize (go);
+          }
+        else
+          proxy->update (pId);
+      }
+  }
+
+  void
+  qt_graphics_toolkit::finalize (const graphics_object& go)
+  {
+    // FIXME: We need to unlock the mutex here but we have no way to know if
+    // if it was previously locked by this thread, and thus if we should
+    // re-lock it.
+    gh_manager::unlock ();
+
+    Logger::debug ("qt_graphics_toolkit::finalize %s from thread %08x",
+                   go.type ().c_str (), QThread::currentThreadId ());
+
+    ObjectProxy *proxy = toolkitObjectProxy (go);
+
+    if (proxy)
+      {
+        proxy->finalize ();
+        delete proxy;
+
+        graphics_object gObj (go);
+
+        gObj.get_properties ().set (toolkitObjectProperty (go), Matrix ());
+      }
+  }
+
+  void
+  qt_graphics_toolkit::redraw_figure (const graphics_object& go) const
+  {
+    if (go.get_properties ().is_visible ())
+      {
+        ObjectProxy *proxy = toolkitObjectProxy (go);
+
+        if (proxy)
+          proxy->redraw ();
+      }
+  }
+
+  void
+  qt_graphics_toolkit::show_figure (const graphics_object& go) const
+  {
+    if (go.get_properties ().is_visible ())
+      {
+        ObjectProxy *proxy = toolkitObjectProxy (go);
+
+        if (proxy)
+          proxy->show ();
+      }
+  }
+
+  void
+  qt_graphics_toolkit::print_figure (const graphics_object& go,
+                         const std::string& term,
+                         const std::string& file_cmd,
+                         const std::string& /*debug_file*/) const
+  {
+    ObjectProxy *proxy = toolkitObjectProxy (go);
+
+    if (proxy)
+      proxy->print (QString::fromStdString (file_cmd),
+                    QString::fromStdString (term));
+  }
+
+  uint8NDArray
+  qt_graphics_toolkit::get_pixels (const graphics_object& go) const
+  {
+    uint8NDArray retval;
+
+    if (go.isa ("figure"))
+      {
+        ObjectProxy *proxy = toolkitObjectProxy (go);
+
+        if (proxy)
+          retval = proxy->get_pixels ();
+      }
+
+    return retval;
+  }
+
+  Matrix
+  qt_graphics_toolkit::get_text_extent (const graphics_object& go) const
+  {
+    Matrix ext (1, 4, 0.0);
+
+    if (go.isa ("uicontrol"))
+      {
+        octave_value str = go.get ("string");
+        if (! str.isempty ())
+          {
+            const uicontrol::properties& up =
+              dynamic_cast<const uicontrol::properties&> (go.get_properties ());
+            Matrix bb = up.get_boundingbox (false);
+            QFont font = Utils::computeFont<uicontrol> (up, bb(3));
+            QFontMetrics fm (font);
+
+            QString s;
+            QSize sz;
+
+            if (str.is_string ())
+              {
+                s = QString::fromStdString (str.string_value ());
+                sz = fm.size (Qt::TextSingleLine, s);
+                ext(2) = sz.width ();
+                ext(3) = sz.height ();
+              }
+            else if (str.iscellstr ())
+              {
+                string_vector sv = str.string_vector_value ();
+                double wd = 0.0;
+                double hg = 0.0;
+                for (octave_idx_type ii = 0; ii < sv.numel (); ii++)
+                  {
+                    s = QString::fromStdString (sv(ii));
+                    sz = fm.size (Qt::TextSingleLine, s);
+                    wd = std::max (wd, static_cast<double> (sz.width ()));
+                    hg = std::max (hg, static_cast<double> (sz.height ()));
+                  }
+
+                ext(2) = wd;
+                // FIXME: Find a better way to determine the height of e.g.
+                // listbox uicontrol objects
+                ext(3) = hg * sv.numel ();
+              }
+          }
+      }
+
+    return ext;
+  }
+
+  Object*
+  qt_graphics_toolkit::toolkitObject (const graphics_object& go)
+  {
+    ObjectProxy *proxy = toolkitObjectProxy (go);
+
+    if (proxy)
+      return proxy->object ();
+
+    return nullptr;
+  }
+
+  ObjectProxy*
+  qt_graphics_toolkit::toolkitObjectProxy (const graphics_object& go)
+  {
+    if (go)
+      {
+        octave_value ov = go.get (toolkitObjectProperty (go));
+
+        if (ov.is_defined () && ! ov.isempty ())
+          {
+            OCTAVE_INTPTR_TYPE ptr = ov.OCTAVE_PTR_SCALAR ().value ();
+
+            return reinterpret_cast<ObjectProxy *> (ptr);
+          }
+      }
+
+    return nullptr;
+  }
+
+  void
+  qt_graphics_toolkit::interpreter_event (const octave::fcn_callback& fcn)
+  {
+    octave::event_manager& evmgr = m_interpreter.get_event_manager ();
+
+    evmgr.post_event (fcn);
+  }
+
+  void
+  qt_graphics_toolkit::interpreter_event (const octave::meth_callback& meth)
+  {
+    octave::event_manager& evmgr = m_interpreter.get_event_manager ();
+
+    evmgr.post_event (meth);
+  }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/graphics/qt-graphics-toolkit.h	Fri Aug 02 12:18:48 2019 -0500
@@ -0,0 +1,94 @@
+/*
+
+Copyright (C) 2011-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_qt_graphics_toolkit_h)
+#define octave_qt_graphics_toolkit_h 1
+
+#include <QObject>
+
+#include "event-manager.h"
+#include "graphics.h"
+
+namespace octave
+{
+  class interpreter;
+}
+
+namespace QtHandles
+{
+  class Object;
+  class ObjectFactory;
+  class ObjectProxy;
+
+  class qt_graphics_toolkit : public QObject, public base_graphics_toolkit
+  {
+    Q_OBJECT
+
+  public:
+
+    qt_graphics_toolkit (octave::interpreter& interp);
+
+    ~qt_graphics_toolkit (void);
+
+    bool is_valid (void) const { return true; }
+
+    void redraw_figure (const graphics_object& h) const;
+
+    void show_figure (const graphics_object& h) const;
+
+    void update (const graphics_object& obj, int pId);
+
+    bool initialize (const graphics_object& obj);
+
+    void finalize (const graphics_object& obj);
+
+    void print_figure (const graphics_object& go,
+                       const std::string& term,
+                       const std::string& file_cmd,
+                       const std::string& /*debug_file*/) const;
+
+    uint8NDArray get_pixels (const graphics_object& go) const;
+
+    Matrix get_text_extent (const graphics_object& go) const;
+
+    static Object * toolkitObject (const graphics_object& go);
+
+    static ObjectProxy * toolkitObjectProxy (const graphics_object& go);
+
+  signals:
+    void createObject (qt_graphics_toolkit *, double handle);
+
+  public slots:
+
+    void interpreter_event (const octave::fcn_callback& fcn);
+    void interpreter_event (const octave::meth_callback& meth);
+
+  private:
+
+    octave::interpreter& m_interpreter;
+
+    ObjectFactory *m_factory;
+  };
+
+}
+
+#endif