octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Connecting Octave to the GUI


From: Daniel J Sebald
Subject: Re: Connecting Octave to the GUI
Date: Mon, 08 Apr 2013 15:15:28 -0500
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.24) Gecko/20111108 Fedora/3.1.16-1.fc14 Thunderbird/3.1.16

On 04/03/2013 05:48 PM, John W. Eaton wrote:
For background info about what follows, please see the comments
attached to this patch tracker entry:

https://savannah.gnu.org/patch/index.php?7990

Dan, I agree that the add/remove_X_hook functions are ugly.

I checked in two changes that I hope will explain what I would like to
do instead. They are here:

http://hg.savannah.gnu.org/hgweb/octave/rev/70032fc70bee
http://hg.savannah.gnu.org/hgweb/octave/rev/169f71c9d9c8

The idea in those patches is to use the octave_link class more the way
I think it was intended. Octave calls methods from this class to
allow the GUI to handle things that happen in the interpreter like
gathering input, entering/exiting the debugger, or calling the edit
function at the command line. Since the octave_link class has pure
virtual functions, it can't work by itself. So the GUI needs to
provide some concrete implementation of those functions and we have
the calls to the GUI that we need. By using this class, we have a
clear definition of what Octave can ask the GUI to do.

My plan is to replace the remaining hook functions that are registered
in the octave_main_thread function with octave_link::calls instead.
Then I'll add new methods for the dialog functions so specialized
GUI versions can be called from the corresponding .m files. I still
think it makes sense to do the argument decoding in the .m files.

It would also be great if we can eliminate the octave_event_listener
class (or at least reduce its usage to to whatever is really
required for handling events while readline is waiting for input).

I've thought some more about this. Things are a bit fuzzy, but it seems to me these hook functions, like callbacks create some extra work that is difficult to keep track of. I see you are doing pre/post input kinds of things, which has merits. But more generally, what I dislike the most about this approach is the requirement of additional little code snippets like this:

              if (! file.empty ())
                octave_link::update_breakpoint (false, file, lineno);

in the core of Octave, as well as calls to so many hook functions and so on. I think there is a much simpler approach that obviates such knowledge from the core.

As a bit of background, one of the innovations of C++ is that inheritance is a well-organized way of doing code reuse. Rather than put conditionals inside of code hunks, inheritance allows to run the base class code and then after that react to or make modifications to the result. I think that is the better concept to strive for. There should hardly need to be any modifications to the Octave side of things. Here is what I think is only needed:

1) Some method of installing Octave builtin functions that can override the present builtin functions and still access the core builtin functions. This is analogous to the C++ inheritance concept. Say the C++ code for the GUI that sets up builtins is something like:

  octave_link = launch_octave_in_another_thread ();
  /* INSTALL */
octave_link->install_octave_command ("dbstop", octave_link::qt_dbstop_routine); octave_link->install_octave_command ("dbclear", octave_link::qt_dbclear_routine); octave_link->install_octave_command ("dbcont", octave_link::qt_dbcontinue_routine);
  etc.

for which an example routine might be:

octave_value_list
octave_link::qt_dbstop_routine (varargs, etc.)
{
  /* ACCESS CORE */
  octave_value_list retval = corefeval ("dbstop", varargs, etc.);

  // Now interpret the retval and its ramifications on Qt GUI elements.
  if (retval[0].is_numeric ())
    {
      QString filename = varargs[0].string_value ().c_str();

      // Found a valid breakpoint.
      emit add_breakpoint (filename, retval[0].int_value());
    }

  return retval;
}

The above code needs no callbacks, hooks, etc. Just the install_octave_command() and corefeval() routine.

2) Some way of queueing up octave commands and getting the result. It is important that this be queued because often the Octave thread could be off processing and the GUI would otherwise be frozen inoperable. Here is an example. In the GUI, say a file is opened and we need to know if there are any breakpoints set in that file. It would be nice to

  emit queue_octave_command ("dbstatus");

In the event queue list would be: 1) the command and 2) QObject pointer identifying what object issued the command, easily gotten from sender().

Say Octave is in the middle of some routine and it won't be fifteen seconds until Octave comes back to the command line. When it does (see #3 that follows) the result could be sent out to all those slots wanting an octave command result:

emit octave_command_complete (QObject *requester, QString& command, octave_value_list& result);

The slot can interpret the result however it wants. In this case the file_editor_tab sifts through the breakpoints and if it finds some with its filename it puts them in the margin. This would happen fifteen seconds after the file has been opened and Octave returns to the command line. Yet, the user could still be doing something in the GUI, which isn't so bad.

3) Possibly some way of being notified that Octave has reached the command line. This is sort of the "post event" kind of hook function that you've written. I'm not 100% sure this is needed (we might find that #2 above covers it), but I think it is. Basically, if after Octave has reached the command line it indicated in some way that it was done and what the result is (could be a single hook function--one is all that is needed), it seems that is all that is needed to do a whole lot of things. For example, if Octave hits a break point it issues something like:

testfun(9)
stopped in /home/sebald/octave/breakpoint/testfun.m at line 7
7: y = log(sx);
debug> dbstep
stopped in /home/sebald/octave/breakpoint/testfun.m at line 9
9: end

Those results are telling all that needs to be known in order to emit a signal that causes a position marker to appear in the editor margin.

Dan


reply via email to

[Prev in Thread] Current Thread [Next in Thread]