Removing __init_qt__ dependency on libgui

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Removing __init_qt__ dependency on libgui

Alex Leach
Hello,

I have been attempting to write a small C++ / Qt application that can interpret Octave scripts and plot figures, using the qt backend. This has been much more difficult than I'd hoped, and I've spent quite a lot of time trying to figure out why the qt backend isn't available to a qt application linked to the octave libraries.

The Qt backend seems to have been originally derived from the QtHandles github repository at https://github.com/goffioul/QtHandles/, with the source code from this repo copied into Octave's libgui/graphics/. Originally, and in the current 5.2.0 release, this was compiled as a standalone module: __init_qt__.oct, but qt figures couldn't easily (at all?) be launched outside of the main GUI.

In the last couple of months however, some of the most recent commits have completely removed compilation of a separate __init_qt__.oct module and compiled this code directly into the main Octave GUI library, as quite rightly, it couldn't be loaded outside of the main GUI anyway.

I would like to propose however, that development of the qt backend go back the other way. Instead of merging and increasing its dependencies on the core GUI, can we try and bring back its modular nature and remove any dependencies on the main GUI?

When the QtHandles was originally developed, it appears there was a very simple tool that would launch the Octave interpreter, and allow launching of the Qt backend:-


This is exactly the sort of thing I'm looking to try and implement, so may I propose that __init_qt__.oct comes back and the module becomes completely decoupled from the main GUI?

Some initial suggestions which may help make this happen (referring to github commit hashes; sorry if hg ones would be easier to follow!):-
  • Some recent commits would need to be reverted: 1a9f05b and bca8e11. These aimed to 'eliminate global access to Octave resources in qt graphics classes', but in the process added a base_qobject argument to many class initialisers all over the qt graphics source code.
  • Would obviously need to revert the commit that stopped compiling a separate module (5dcc746).
  • Any references to the GUI's resource manager need to be removed. I think there are only a couple, used to get mouse and toolbar icons (Canvas.cc and ToolBarButton.cc, respectively), and a window position (annotation-dialog.cc). Are the mouse icons used by the GUI elsewhere? Maybe these icons can be moved into a libgui/graphics/icons/ folder, if they're only used by qthandles figures? Is there any reason libgui/graphics can't have its own resource file?
  • libgui/graphics/__init_qt__.cc. In release 5.2.0, there was a PKG_ADD line that tests for __octave_link_enabled__(). Without a global instance of octave_link, the module won't load at all. No warning is produced, so this took me a while to figure out. Now the test shows __event_manager_enabled__. Can any of these requirements either be removed, or just get the qt handles module to initialise these things itself?
I don't think there's a huge amount else to do, but that's probably easier said than done!

As the Octave maintainers, would you be interested in seeing the qt handles backend completely decoupled from the main GUI and made strictly modular again?

Kind regards,
Alex
Reply | Threaded
Open this post in threaded view
|

Re: Removing __init_qt__ dependency on libgui

John W. Eaton
Administrator
On 11/11/20 5:22 AM, Alex Leach wrote:

> I would like to propose however, that development of the qt backend go
> back the other way. Instead of merging and increasing its dependencies
> on the core GUI, can we try and bring back its modular nature and remove
> any dependencies on the main GUI?

If I understand correctly, you are proposing that the Qt plotting code +
Octave interpreter be usable without the Octave GUI?  That seems
reasonable, and I'm willing to work in that direction if you would like
to help with defining how these components should work together and be
initialized.  As you note, however, the Qt graphics code is not usable
without the Octave interpreter.  So why not have your application start
the interpreter and interact with it to create plots using the Qt
graphics code?

jwe

Reply | Threaded
Open this post in threaded view
|

Re: Removing __init_qt__ dependency on libgui

Alex Leach
From: John W. Eaton <[hidden email]>
Sent: 11 November 2020 18:52
To: Alex Leach <[hidden email]>; [hidden email] <[hidden email]>
Cc: [hidden email] <[hidden email]>
Subject: Re: Removing __init_qt__ dependency on libgui
 
If I understand correctly, you are proposing that the Qt plotting code +
Octave interpreter be usable without the Octave GUI?  That seems
reasonable, and I'm willing to work in that direction if you would like
to help with defining how these components should work together and be
initialized. 
Thanks for the response John, and apologies for the slow reply. Yes, you've hit the nail on the head, thanks and I'm glad that you think this is a reasonable proposition. I've had a good think about how I think these components could, or should be initialised, as had previously just been thinking of target objectives. I'll summarise these below.

As you note, however, the Qt graphics code is not usable
without the Octave interpreter.  So why not have your application start
the interpreter and interact with it to create plots using the Qt
graphics code?

This was exactly what I had originally been attempting, however I was really struggling to get it to work. My 'simple' example got larger and larger as I was implementing various derived classes (e.g. octave_link) in attempts to get figures to show with the qt backend, using the 5.2.0 release code. I finally got the figures to show, but none of the toolbar or menubar buttons worked. I then noticed the really small example file in the original QtHandles github repository (that I linked to in my previous email) and realised a small example might not need to be any more complicated than that. However, over the last year or two, dependencies on the main GUI have crept in to the qthandles code, so that when I ran the example (replacing octave_main with octave::cli_application, then executing that), loading __init_qt__ results in missing symbol errors from liboctgui. Linking against liboctgui would fix these issues, but I think should be unnecessary.

Anyway, looking ahead, and I'm really grateful you would be willing to help and work in this direction, I'll try to help with some definitions as you've asked for.

Initialising

  • If I understood the way qthandles originally initialised, I think that made a lot of sense: as a package. It seems this happens automatically when compiled into the __init_qt__.oct module, through the PKG_ADD mechanism.
  • The PKG_ADD statement that was added to __init_qt__.cc would ideally be simpler. The `__octave_link_enabled__' and then `__event_manager_enabled__' tests would ideally be removed, if possible? The original test (in C++) that was still in the last version of __init_qt__.cc was `if (qApp) else error(...)'. Can we move that test into the PKG_ADD line, and load the package on that basis alone? There's already an `if (__have_feature__ ("QT") )` test, is this equivalent to `if(qApp)`?

So, overall, I think the mechanisms of initialisation were designed quite well in the first place. However, maybe the reason more tests were added and it got more complicated was that the extra event_manager / octave_link instances were absolutely required to be initialised outside of qthandles?

Event Manager / Octave Link

Looking at this more, I wonder if the event_manager definition can be simplified. In my app (when compiled against 5.2.0), a lot of the abstract functions were unnecessary, but I had to implement them regardless in order to subclass octave_link and enable it. As the interpreter initialises an event_manager anyway, can we just use that base definition and implement it as a dynamic callback manager, with just a few generic methods, in place of all the dialog and preference methods, something like:-

void event_manager::register_callback(std::string event_name, octave::octave_fcn cb);

octave_value_list event_manager::execute_callback(std::string event_name, octave_value_list args);

This sort of mechanism could get rid of a lot of the hardcoded _dialog methods, I think. Then, in the __init_qt__ extension (or any other extension), the appropriate callbacks are registered to override any set defaults. Is this something you think might work?


Objectives / Tests

  • I think if the original octave-qt tool (https://github.com/goffioul/QtHandles/blob/master/tool/octave-qt.cpp) could be compiled and run successfully, with the qt backend registered and used to display figures, that would make a good test. I don't know how to go about implementing this as part of the test suite, other than compiling and running it manually however.
  • The code in libgui/graphics should not need to include libgui/src. i.e. the CPPFLAG -Ilibgui/src should be removed.
  • uigetdir, uigetfile, uiputfile should call the qt backend once it's been initialised. Using the mechanism above, relevant callbacks could be registered?
To do

Other than the event manager stuff, I've tried making a stab at removing any dependency on libgui/src, and have made a fork on github, at https://github.com/alexleach/octave/tree/qthandles. I might have made a bit of a mess of the commit history (sorry!), but it seems to be working okay for launching a figure Container and Canvas.

What isn't working are the Qt widgets for uigetfile / uiputfile / uigetdir, I guess because I don't have an event manager. Another thing that isn't working (in this or the fltk backend), are the buttons for 'Show / Toggle / Hide grid on all axes'; these only affect the currently active axis, but I haven't looked into this much.

If there's anything else I can do to make this easier to implement, please let me know.

Best wishes,
Alex
Reply | Threaded
Open this post in threaded view
|

Re: Removing __init_qt__ dependency on libgui

Alex Leach


From: Alex Leach <[hidden email]>
Sent: 17 November 2020 10:27
To: John W. Eaton <[hidden email]>; [hidden email] <[hidden email]>
Subject: Re: Removing __init_qt__ dependency on libgui
 
  • uigetdir, uigetfile, uiputfile should call the qt backend once it's been initialised. Using the mechanism above, relevant callbacks could be registered?
To do

What isn't working are the Qt widgets for uigetfile / uiputfile / uigetdir, I guess because I don't have an event manager. 

As an addendum, I've finally tracked this one down, spent ages looking for where the function names e.g. __uigetfile_fltk__ get constructed, and have just found it, in scripts/gui/private/__get_funcname__.m.

Again, a test for __event_manager_enabled__ blocks calling the qt implementations of these functions. A quick removal of this test seems to get them all working fine. Is there a reason that I'm not seeing for requiring the octave link / event manager here?

Have just made a small commit, at https://github.com/alexleach/octave/commit/9ca4510aa4aabd0f08e4f8759001eada14fc4063. Any thoughts on this?

Kind regards,
Alex
Reply | Threaded
Open this post in threaded view
|

Re: Removing __init_qt__ dependency on libgui

John W. Eaton
Administrator
In reply to this post by Alex Leach
On 11/17/20 5:27 AM, Alex Leach wrote:
> *From:* John W. Eaton <[hidden email]>

>     As you note, however, the Qt graphics code is not usable
>     without the Octave interpreter.  So why not have your application start
>     the interpreter and interact with it to create plots using the Qt
>     graphics code?
>
> This was exactly what I had originally been attempting, however I was
> really struggling to get it to work. My 'simple' example got larger and
> larger as I was implementing various derived classes (e.g. octave_link)
> in attempts to get figures to show with the qt backend, using the 5.2.0
> release code. I finally got the figures to show, but none of the toolbar
> or menubar buttons worked. I then noticed the really small example file
> in the original QtHandles github repository (that I linked to in my
> previous email) and realised a small example might not need to be any
> more complicated than that. However, over the last year or two,
> dependencies on the main GUI have crept in to the qthandles code, so
> that when I ran the example (replacing octave_main with
> octave::cli_application, then executing that), loading __init_qt__
> results in missing symbol errors from liboctgui. Linking against
> liboctgui would fix these issues, but I think should be unnecessary.

OK.  My goals for the Qt graphics code in Octave was focused mostly on
getting it to work better in the context of the Octave GUI and I wanted
to eliminate the global access to the interpreter and GUI objects.

But before we go too far discussing details, I'd like to agree on the
goals.  How do you want to use the Octave graphics code?  I imagine that

   octave::interpreter octave_interpreter (...);
   QOctaveGraphics *graphics_widget
     = new QOctaveGraphics (parent_qt_widget, octave_interpreter);

where you create the graphics widget that is linked to your already
initialized embedded Octave interpreter or perhaps

   QOctaveGraphics *graphics_widget
     = new QOctaveGraphics (parent_qt_widget);

and the QOctaveGraphics widget will initialize it's own interpreter
object would be reasonable.  However, due to global variable usage in
the interpreter, only one Octave interpreter is allowed in a given
process so only one graphics object could be created this way.

Is that the kind of thing you would like to do?  If so, how would you
interact with this object?  Would you use interpreter functions to
create plots or would you use Qt signals to pass data and plot options
to the graphics widget?

jwe

Reply | Threaded
Open this post in threaded view
|

Re: Removing __init_qt__ dependency on libgui

Alex Leach


From: John W. Eaton <[hidden email]>
Sent: 17 November 2020 16:34
To: Alex Leach <[hidden email]>; [hidden email] <[hidden email]>
Subject: Re: Removing __init_qt__ dependency on libgui
 
OK.  My goals for the Qt graphics code in Octave was focused mostly on
getting it to work better in the context of the Octave GUI and I wanted
to eliminate the global access to the interpreter and GUI objects.
Okay. I guess eliminating global access to the interpreter allows for multiple interpreters? And eliminating global access to GUI objects sounds like my goal? Is there anywhere in particular you have in mind, where the Qt graphics code doesn't work well with the Octave GUI?

But before we go too far discussing details, I'd like to agree on the
goals.  How do you want to use the Octave graphics code?  I imagine that

   octave::interpreter octave_interpreter (...);
   QOctaveGraphics *graphics_widget
     = new QOctaveGraphics (parent_qt_widget, octave_interpreter);

where you create the graphics widget that is linked to your already
initialized embedded Octave interpreter or perhaps

   QOctaveGraphics *graphics_widget
     = new QOctaveGraphics (parent_qt_widget);

and the QOctaveGraphics widget will initialize it's own interpreter
object would be reasonable.  However, due to global variable usage in
the interpreter, only one Octave interpreter is allowed in a given
process so only one graphics object could be created this way.

I think either should work fine, but the second case might be easier, as the GUI and the interpreter need to run in separate threads, especially for long running scripts. Initially, I was just trying to embed an interpreter without creating separate threads, and using the very simple example documentation at https://octave.org/doc/v5.2.0/Standalone-Programs.html as inspiration. I then realised I had long running scripts and needed a separate worker thread for the interpreter. Further, separate threads allows a progress bar to be updated, which is nice.

Is that the kind of thing you would like to do?  If so, how would you
interact with this object?  Would you use interpreter functions to
create plots or would you use Qt signals to pass data and plot options
to the graphics widget?

My current effort is to create a subclass of QApplication and another of QMainWindow. The Application launches a separate worker thread and it's this that runs the interpreter. The MainWindow and its child widgets emit signals which effectively call octave functions indirectly, through the worker thread:-

public slots:
octave_value_list call_octave_fcn( const QString &fcn_name, octave_value_list args );

Then, a couple of signals for sending status updates and the end result back:-

void status_update( const SomeStatusEnum &status);
void send_results( octave_value_list retval );

But this is all interacting with the interpreter of course, not the plots or figure window. Personally, I have no need to control the figures directly from C++. I have some long-running .m files that plot their data at the end on various sub-plots, and it's these that I'd like shown on the Qt backend.

The other thing that I've already hinted at, which would be nice for consistency purposes in my Qt / C++ app: I launch QFileDialog windows to select files and/or folders (these are what go into my 'args' for the call to octave). When the figure windows are shown by the Octave script, it would be nice if when clicking Save As, I'd have Qt dialogs show, instead of the ftlk ones. Seems a bit odd having two kinds of file dialog within a single app: Qt dialogs for my code, fltk for the Octave scripts.

On that note, I found out the hard way why __get_funcname__.m tests for __event_manager_enabled__. The uigetdir/uigetfile, etc. functions in __init_qt__.cc need to call QFileDialog static functions from the GUI thread, which they don't do without the event manager. Nice seg-fault if you try using them without an event manager. I came up with a work-around that doesn't require the event manager, but I'm sure this could be improved upon.

Hope that answers some of your questions anyway, and is constructive in the right direction! Do you think there are any major obstacles to implementing this?

Kind regards,
Alex
Reply | Threaded
Open this post in threaded view
|

Re: Removing __init_qt__ dependency on libgui

John W. Eaton
Administrator
On 11/17/20 1:14 PM, Alex Leach wrote:

> *From:* John W. Eaton <[hidden email]>

>     But before we go too far discussing details, I'd like to agree on the
>     goals.  How do you want to use the Octave graphics code?  I imagine that
>
>         octave::interpreter octave_interpreter (...);
>         QOctaveGraphics *graphics_widget
>           = new QOctaveGraphics (parent_qt_widget, octave_interpreter);
>
>     where you create the graphics widget that is linked to your already
>     initialized embedded Octave interpreter or perhaps
>
>         QOctaveGraphics *graphics_widget
>           = new QOctaveGraphics (parent_qt_widget);
>
>     and the QOctaveGraphics widget will initialize it's own interpreter
>     object would be reasonable.  However, due to global variable usage in
>     the interpreter, only one Octave interpreter is allowed in a given
>     process so only one graphics object could be created this way.
>
>
> I think either should work fine, but the second case might be easier, as
> the GUI and the interpreter need to run in separate threads, especially
> for long running scripts.

We will probably need some variation of the first for using it with the
Octave GUI, where the interpreter (or interpreter running in a separate
thread) will already exist.

> My current effort is to create a subclass of QApplication and another of
> QMainWindow. The Application launches a separate worker thread and it's
> this that runs the interpreter. The MainWindow and its child widgets
> emit signals which effectively call octave functions indirectly, through
> the worker thread:-
>
> public slots:
> octave_value_list call_octave_fcn( const QString &fcn_name,
> octave_value_list args );
>
> Then, a couple of signals for sending status updates and the end result > back:-
>
> void status_update( const SomeStatusEnum &status);
> void send_results( octave_value_list retval );
>
> But this is all interacting with the interpreter of course, not the
> plots or figure window.

OK.  If the Octave interpreter were also packaged as a Qt object with
public signals and slots, what set of signals and slots do we need?

Currently, the GUI has some signals that it can emit to invoke Octave
functions or, using C++ lambda expressions, run arbitrary code inside
the interpreter thread.  Those lambda expressions can then emit Qt
signals directly rather than using the octave event manager class.

As you mentioned earlier, it would be good to simplify the event manager
object.

> The other thing that I've already hinted at, which would be nice for
> consistency purposes in my Qt / C++ app: I launch QFileDialog windows to
> select files and/or folders (these are what go into my 'args' for the
> call to octave). When the figure windows are shown by the Octave script,
> it would be nice if when clicking Save As, I'd have Qt dialogs show,
> instead of the ftlk ones. Seems a bit odd having two kinds of file
> dialog within a single app: Qt dialogs for my code, fltk for the Octave
> scripts.

I'm not sure where fltk dialogs are coming from?  It should be possible
for them to all be based on Qt widgets.

jwe


Reply | Threaded
Open this post in threaded view
|

Re: Removing __init_qt__ dependency on libgui

John W. Eaton
Administrator
In reply to this post by Alex Leach
On 11/11/20 5:22 AM, Alex Leach wrote:

>   * Some recent commits would need to be reverted: 1a9f05b and bca8e11.
>     These aimed to 'eliminate global access to Octave resources in qt
>     graphics classes', but in the process added a base_qobject argument
>     to many class initialisers all over the qt graphics source code.

Looking at this now, I see that the base_qobject object is just used for
access to the resource manager (see additional comments about that below).

The interpreter object is primarily used to access the gh_manager mutex
object.  I don't think locking is really handled correctly now.  Fixing
that might completely avoid the need for direct access to the gh_manager
mutex in the graphics code.  Or, if we do decide that the right way is
to lock the gh_manager object in the Qt graphics thread, then maybe we
could come up with a better way to do that?

Other than locking, the gh_manager object is also used to get
graphics_object objects.  Are there better ways of doing that job?  Can
we just emit signals that request something and then respond to a signal
that comes back from the interpreter?  Or in some instances do we need
to suspend execution and wait for the result before allowing the
graphics thread to continue processing?  For example, similar to the
interpreter_event signals that we have, maybe we could use something like

   emit gh_manager_event ([=] (gh_manager& gh_mgr) { ... });

and have the gh_manager_event processed by the qt_graphics_toolkit
object (same as the interpreter_event) and at that point we could access
the gh_manager object without needing to pass it around to all the
sub-objects that make up the Qt graphics widget.

Whatever we do, we need thread-safe access to the graphics objects that
are stored in the gh_manager in the interpreter thread and I don't think
that has ever been done 100% correctly.

The interpreter is also used to get access to the event manager object,
but that only happens in qt-graphics-toolkit.cc.  We probably don't need
to worry about the direct access to the interpreter in that file.  For
the rest.

>   * Any references to the GUI's resource manager need to be removed. I
>     think there are only a couple, used to get mouse and toolbar icons
>     (Canvas.cc and ToolBarButton.cc, respectively), and a window
>     position (annotation-dialog.cc). Are the mouse icons used by the GUI
>     elsewhere? Maybe these icons can be moved into a
>     libgui/graphics/icons/ folder, if they're only used by qthandles
>     figures? Is there any reason libgui/graphics can't have its own
>     resource file?

I assume we'd like to have one configuration dialog for the Octave GUI
that also allows setting of these resources?  Can that configuration
dialog use two separate resource files?  If the graphics widget may also
be used separately, does it need a separate configuration editor?

jwe

Reply | Threaded
Open this post in threaded view
|

Re: Removing __init_qt__ dependency on libgui

Alex Leach
Thanks for your notes and thoughts John. This is probably a good point to admit that I'm not particularly a guru with C++, especially with features introduced in C++11 and beyond, e.g. lambdas, so not sure how much help or advice I can offer with some of your below questions. Hopefully some of the other maintainers can chip in with suggestions here, though.


From: John W. Eaton <[hidden email]>
Sent: 17 November 2020 21:36
To: Alex Leach <[hidden email]>; [hidden email] <[hidden email]>
Subject: Re: Removing __init_qt__ dependency on libgui
 
Looking at this now, I see that the base_qobject object is just used for
access to the resource manager (see additional comments about that below).
So, no issue getting rid of the base_qobject then, by the sounds of it?
The interpreter object is primarily used to access the gh_manager mutex
object.  I don't think locking is really handled correctly now.  Fixing
that might completely avoid the need for direct access to the gh_manager
mutex in the graphics code.  Or, if we do decide that the right way is
to lock the gh_manager object in the Qt graphics thread, then maybe we
could come up with a better way to do that?

This is something that hopefully some of the other maintainers can offer advice on, as my knowledge on proper implementation of thread-safety is limited, at best.

Other than locking, the gh_manager object is also used to get
graphics_object objects.  Are there better ways of doing that job?  Can
we just emit signals that request something and then respond to a signal
that comes back from the interpreter?  Or in some instances do we need
to suspend execution and wait for the result before allowing the
graphics thread to continue processing?  For example, similar to the
interpreter_event signals that we have, maybe we could use something like

   emit gh_manager_event ([=] (gh_manager& gh_mgr) { ... });

and have the gh_manager_event processed by the qt_graphics_toolkit
object (same as the interpreter_event) and at that point we could access
the gh_manager object without needing to pass it around to all the
sub-objects that make up the Qt graphics widget.

Whatever we do, we need thread-safe access to the graphics objects that
are stored in the gh_manager in the interpreter thread and I don't think
that has ever been done 100% correctly.

The interpreter is also used to get access to the event manager object,
but that only happens in qt-graphics-toolkit.cc.  We probably don't need
to worry about the direct access to the interpreter in that file.  For
the rest.

>   * Any references to the GUI's resource manager need to be removed. I
>     think there are only a couple, used to get mouse and toolbar icons
>     (Canvas.cc and ToolBarButton.cc, respectively), and a window
>     position (annotation-dialog.cc). Are the mouse icons used by the GUI
>     elsewhere? Maybe these icons can be moved into a
>     libgui/graphics/icons/ folder, if they're only used by qthandles
>     figures? Is there any reason libgui/graphics can't have its own
>     resource file?

I assume we'd like to have one configuration dialog for the Octave GUI
that also allows setting of these resources?  Can that configuration
dialog use two separate resource files?  If the graphics widget may also
be used separately, does it need a separate configuration editor?

As far as I'm aware, there's nothing configured by the graphics toolkit in the resource manager, no? The resource manager icons are pretty static in nature; either theme icons are pulled from the system theme, or otherwise through the Qt resource file, the latter which is statically compiled into the shared library module. The annotation dialog's window position is currently saved through the resource manager, but there's no user configuration required here; it just saves its position and when next opened, opens in the same position. This should be easily achieved through graphics library having its own QSettings object.


OK.  If the Octave interpreter were also packaged as a Qt object with
public signals and slots, what set of signals and slots do we need?

Currently, the GUI has some signals that it can emit to invoke Octave
functions or, using C++ lambda expressions, run arbitrary code inside
the interpreter thread.  Those lambda expressions can then emit Qt
signals directly rather than using the octave event manager class.

As you mentioned earlier, it would be good to simplify the event manager
object.

I've just had a look through event-manager.h, as spent more time familiarising myself with octave_link in the 5.2.0 code, and noticed that it has been split into two classes: interpreter_events and event_manager, which seems logical from a multi-threading point of view. It looks like event_manager only has one virtual function now, so would be much simpler to derive from, for my purposes at least, but I'd still need to subclass interpreter_events and they both have many methods that I just wouldn't need to use at all; all I need are QFileDialog instances.
 
As I say, I'm no guru, but I think your FIXME comment in event-manager.h is exactly on the same line as I was thinking:-

 // FIXME: it would be nice if instead of requiring the GUI to derive
 // from this class, it could subscribe to individual events, possibly
 // multiple times.  In that way, it would be more flexible and
 // decentralized, similar to the Qt signal/slot connection mechanism
 // and would allow the GUI to connect multiple signals to a single
 // action or multiple actions to a single signal.

I don't know how easy this would be to implement, but I imagine it would be quite a major change and would affect many areas of the codebase. Further, I think the registered events would need to be well-documented somehow, or at least introspectable to get a list of created events.

I'm not sure where fltk dialogs are coming from?  It should be possible
for them to all be based on Qt widgets.
Two reasons: 1) __get_funcname__.m, called by uigetdir.m, etc. will default to calling e.g. __uigetdir_fltk__, and 2) __init_qt__.cc, before it was removed, actually had a preprocessor #if 0 statement around all the DEFUN_DLD definitions of __uigetfile_qt__ and the other related dialog functions. I think they were all essentially commented out, as the Qt widgets I guess are called by the event manager now?

Hope some of the above is of use.

KR, Alex