patchGNU Octave - Patches: patch #7990, Add builtin Qt equivalents of UI...

 
 

patch #7990: Add builtin Qt equivalents of UI dialogs, i.e.,, qterrordlg, qtinputdlg, etc.

Submitter:  Dan Sebald <sebald>
Submitted:  Mon 01 Apr 2013 10:58:12 PM UTC
   
 
Category:  None Priority:  5 - Normal
Status:  Done Privacy:  Public
Assigned to:  None Open/Closed:  Closed
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Wed 04 Sep 2013 01:12:53 AM UTC, comment #28: 

Perhaps.  The GUI hasn't gotten the testing I imagined it would at this point.

The reason this remained open is because the signal/slot across threads was a new, untested approach at the time.  Right now the code does not have the extra test that I'm certain will not hang the system.  The question is if we want to add it to be safe or leave well enough alone to run the gamut of beta testers.

There have been others starting to work with a mutex, so I think there's no fear of this being some enigma down the road.  I'm alright with closing this, as I think the mutex technique is going to come into broader discussion as more seamless interaction is desired at some point, and it will be refined in the places it is used.

Dan Sebald <sebald>
Wed 04 Sep 2013 12:25:03 AM UTC, comment #27: 

Can this patch for Qt UI dialogs be closed?  I think the work has been committed into the core.

Rik <rik5>
Group administrator
Fri 26 Apr 2013 06:31:59 PM UTC, comment #26: 

I should point out that I ran this on a system with multiple cores.  Maybe there is never a reason for the worker thread to be interrupted because each thread can have its own CPU.  I'll check if there is some way to run under one CPU, but if it isn't an easy thing to do I probably won't put too much effort into it.  I'd just as soon go with adding the extra lock on the GUI thread side.

Dan Sebald <sebald>
Fri 26 Apr 2013 05:57:45 PM UTC, comment #25: 

I've tested the waitcondition behavior of the question dialog as described in the diff file and script file attached to this post.  The test was to repeatedly simulate a button press by passing in an extra variable to the questdlg function that represents the index of the button that the main window should click after creating the dialog.

I ran two tests, the difference being the following:

The first test checks that the mutex can be locked before awakening the worker process.

  if (! mutex.tryLock (5000))
    {
      [snip error message]
    }
  else
    {
      mutex.unlock ();
      waitcondition.wakeAll ();
    }


The second test does not check for a lock, but simply awakes the worker process.

   // Wake up Octave process so that it continues.
   waitcondition.wakeAll ();


Neither of these tests failed once in 1 million trials:


>> wctest
errors = 0
Elapsed time is 1e+04 seconds.



>> wctest
errors = 0
Elapsed time is 1e+04 seconds.


I'm surprised.  I was expecting the latter approach which does not check for a lock to fail either by freezing or by getting the default result rather than the button click result.

What I was trying to test with the above patch applies to this code on the worker side of the signal/slot divide:


  uiwidget_creator.signal_dialog (QString::fromStdString (msg),
                                  QString::fromStdString (title),
                                  QString::fromStdString (dlg),
                                  QStringList (), QString (),
                                  QStringList ());

  // Wait while the user is responding to message box.
  uiwidget_creator.wait ();


Does it not seem that the thread could be interrupted between the signaling of the dialog creation and going into the wait/sleep state?  That would leave open the possibility that the GUI thread gets a little ahead of things and awakes the worker thread before it has actually gone to sleep.  Apparently that isn't the case though, but I can't explain why not.  I suppose it is a good outcome, but maybe it is OS dependent or is just more rare than one in a million.  Don't know.

So, what should we do here?  Go with what seems like the more robust approach (i.e., check for a lock...I'll create a changeset).  Or try and explain why there is no failure without checking for a lock?




(file #27953, file #27954)

Dan Sebald <sebald>
Mon 22 Apr 2013 08:06:59 PM UTC, comment #24: 

octave_link_enabled is good.  That's really what is being tested.

Yeah, I don't know about the NR/NC.  I tried to match the Java equivalent behavior.  I would be fine with making this pixels.  (In fact, that seems to make more sense given that there is some parameter in one of these dialogs has a size specification in pixels.)  But the NR/NC seem to be something on the order of character heights and widths.  In that case, fractional specifications seem more worthwhile than whole jumps from, say, 1 character height to 2 character heights.

I'm alright with any changes to this dialog stuff.  Seems like an evolving thing.

Dan Sebald <sebald>
Mon 22 Apr 2013 07:18:30 PM UTC, comment #23: 

I applied this changeset with a few additional changes.

The function isguirunning wasn't included.  I created a function called _octave_link_enabled_ in a separate changeset and used that instead.

As I remember, QStringList::fromStdList (prompt) does "work", but it doesn't do what we need.  We need a std::list<std::string> object, but I think the fromStdList function produces a QList of std::string objects.

Aren't the nr and nc dimentions pixel values?  If so, then
it seems to me that it would make more sense to use ints and do whatever is needed to get the math right internally instead of exposing floats where they don't really make sense.

John W. Eaton <jwe>
Group administrator
Mon 22 Apr 2013 05:07:41 PM UTC, comment #22: 

No real difference between this changeset and yesterday's.  Just some cleanup of documentation and cruft.

(file #27927)

Dan Sebald <sebald>
Sun 21 Apr 2013 10:01:03 AM UTC, comment #21: 

Attached are some fixes and an implementation of questdlg.  I will intersperse some comments below with the changeset comment.  Please leave this patch report open because there is one thing I want to test at a later time; the waitcondition behavior, see if I can break it.

COMMENTS:

  • I changed all the conditional tests for platform inside the dialogs to this format:



  if (isguirunning ())
    __octave_link_XYZ__ ()
  elseif (__have_feature__ ("JAVA"))
    javaMethod ()
  else
    error ();
  endif


It makes sense that "isguirunning" coincides with octave_link".  The other ways that this was conditioned all seemed to have bugs because the return condition of some of the dialogs returned values that make the condition pass.  For example, canceling instead of selecting a button would produce a 0 for Ok.

  • octave-qt-link.cc (octave_qt_link::do_message_dialog):

Change initializer from QString() to QString::fromStdString (dlg).

The icons were missing from the dialogs.

  • (octave_qt_link::do_list_dialog): Change std string 'prompt_string' to list list of std string 'prompt'.


I set the prompt string to accept Rich Text (html) code.  This may not ultimately be compatible with the definition, but I wanted to just try it to see what the response is, how well it works etc.  I see that you were trying to test RTF format with the \\alpha value.  (I don't think the list entries have an RTF or RT "delegate".  Can be done, but tricky.)

Anyway, the cell list structure needs to be carried all the way to the use because <br> is the carriage return in Rich Text, not \n.  I left a define in the code to control the interpretation.

  • Use make_qstring_list (prompt).


Why doesn't this work?:  QStringList::fromStdList (prompt)
Just curious.

  • (octave_qt_link::do_input_dialog): Change 'nr' and 'nc' to std list of float. Use QFloatList::fromStdList (nc).


I changed the nr and nc of the input dialog list sizes to QFloatList instead of QIntList and then made the listdlg do rounding upward.  If you'd prefer to use integer list all the way through, feel free to change it back.  Or let me know and I'll create a separate patch which removes the QFloatList definition, registration and all.

  • errordlg.m (errordlg): Make retval return variable.


The return value wasn't showing up at the command line.

  • Add "error" icon as message_dialog input.


Missing icon.

  • message_dialog.m (message_dialog): Define default icon, "none".


Was creating error of missing icon variable under certain conditions.

  • Remove FIXME note.


I felt that FIXME was more a TODO than a FIXME.  And it is somewhat low priority, since a terminal based implementation would be kind of clunky.  How would one handle a long list of items that gets dumped into the pager?  Also, a programmer could come up with their own question/answer sort of terminal interaction easily enough.  Lastly, it pretty clear where the terminal-based implementation would go if someone really wanted to create one.

  • listdlg.m (listdlg): Change default selmode from "multiple" to "Multiple".


This was causing problems in a demo.  "multiple" is unrecognized so the list was turning out to be non-selectable.  I added a check to make sure the user enters a valid selection mode.  That really should be there in any case.

  • Make default prompt {}.


With {""} as the default prompt, the prompt has to be interpretted as a blank line.  (Imagine that is what the user entered.)  The only way to get no prompt is to make the cell list empty.

  • questdlg.m (questdlg): Add case 0 to switch.


Bug when no inputs beyond the basics.  A scenario not tested by the demos.

  • Add error message for default button not matching options. In all cases, check that default button matches an button option.


Got to have this otherwise it is too easy for the user to type a mistake and not realize the default isn't set.  These things can be confusing, so I think it is worth pointing out the error.

  • dialog.cc (QUIWidgetCreator::dialog_finished): Remove.

(QUIWidgetCreator::dialog_button_clicked): Test that button pointer nonzero.
Move dialog_result assignment and waitcondition.wakeAll here.

Took forever to find a decent setup.  The ESC key is automatically attached to a button in most cases.  When that happens, both a button press and a rejected() is emitted.  The upper close tab is associated with rejected().  End result was a race condition between causing two "Awakes" to occur.  Sometimes a couple dialogs would appear in a string of questions.  I over-road the closeEvent behavior to make only one route out of that dialog, "buttonClicked".

  • (MessageDialog::MessageDialog): If title "", change to " ".


The default system title was showing up in the window header bar with an empty string.  I don't think we ever want to see that.  A blank header is preferred if user hasn't specified.


(file #27917)

Dan Sebald <sebald>
Thu 18 Apr 2013 09:49:08 PM UTC, comment #20: 

I didn't initially read the previous post all the way through.  Debugging some other parts of the changeset, I noticed there is no question dialog and started working on that.  What I'm doing is adding:

DEFUN (_octave_link_question_dialog_, args, ,
  "-*- texinfo -*-\n\
@deftypefn {Built-in Function} {} _octave_link_question_dialog_ (@var{msg}, @var{title}, @var{btn1}, @var{btn2}, @var{btn3}, @var{default})\n\

because the question dialog is different enough from the regular message box, even though it is more general and covers what the regular message box does.  That's probably not immediately evident to a programmer.

I'll still use the general MessageDialog at the Qt level.

Dan Sebald <sebald>
Sat 13 Apr 2013 07:37:18 PM UTC, comment #19: 

I checked in a modified version of this patch that uses octave_link calls from the existing dialog functions (.m files) instead of having the GUI completely replace those functions.

I think we still need a version for questdlg.  If someone wants to work on it, please post a message here or on the maintainers list when you start so we don't duplicate effort.

John W. Eaton <jwe>
Group administrator
Wed 03 Apr 2013 10:37:00 PM UTC, comment #18: 

Moving to discussion list is good.  I'll look at the dbstop proof-of-concept later this evening and create a different patch report.

Dan Sebald <sebald>
Wed 03 Apr 2013 10:32:28 PM UTC, comment #17: 

How about moving this discussion to the maintainers list?

I'll posted some info there about a change I've just committed.

John W. Eaton <jwe>
Group administrator
Wed 03 Apr 2013 03:59:57 PM UTC, comment #16: 

Dan, let's take the example of dbstop and convert it to the method you propose.  If we do that, then maybe I will be able to follow what you are proposing.  But I need more information about precisely what the debug_manager class should be doing and where the signals are supposed to be declared.

John W. Eaton <jwe>
Group administrator
Wed 03 Apr 2013 03:48:47 PM UTC, comment #15: 

If possible, I don't want to pass commands as strings back to Octave from the GUI.

But otherwise, if there is some way that we can avoid calling octave_link::do_process_events, that's fine with me.

John W. Eaton <jwe>
Group administrator
Wed 03 Apr 2013 03:40:17 PM UTC, comment #14: 

Yes, there is a potential problem for the add/remove hook functions.  Maybe they should be named _X_ instead, to indicate that they are functions for "internal" use.

In any case, I don't think we want to invent some new complicated way of dealing with these functions.  The GUI should install them when it starts, and the hook function idea works.  For a related set of functions like the Xdlg functions, we can use a struct to set all of the hooks with one function call.

Since these functions are supposed to provide the same interface regardless of whether the GUI is qt/gtk/whatever, they should not be providing the help text.  That should be done in one place so that the help text is consistent for all possibile implementations.

John W. Eaton <jwe>
Group administrator
Wed 03 Apr 2013 08:42:59 AM UTC, comment #13: 

OK, back to the topic of incorporating the "qterrordlg", "qtinputlist", etc. routines, generally speaking.  It seems everything we've thought of to this point adds extra functions to the namespace which risks being overridden.

The only other thing that I can think of that seems not prone to this problem is to place all of these routines in a library that can be installed at startup.  For example, say I've gone through the process of creating a bunch of builtin functions that communicate with the GUI, whether it be GTK or Qt.  Furthermore, all of these routines have the exact same configuration of some existing routine in the namespace.  Say I have a couple files for Qt:


<qtdialog.cc>
DEFUN("qterrordlg"...)
DEFUN("qtquestdlg"...)
so on



<qtdebug.cc>
DEFUN("qtdbclear"...)
DEFUN("qtdbstop"...)
so on


Say I've tested those to my satisfaction.  Now, let's say there is a mechanism in the Make process (doesn't currently exist and not sure it is possible) that will compile those files into object files and create a library.  A library that can be loaded by Octave at startup, and Octave places the function names into the namespace AND replaces any existing builtins with the same name YET somehow allows those original functions to be accessed because I might want to still call some existing behavior of Octave (e.g., dbstop).  (Sort of like in C++ how one can access a function of the base class by doing baseclass::function().)

So, what I do when I'm all set, is change the file names to:


<qtdialog.cc>
DEFUN("errordlg"...)
DEFUN("questdlg"...)
so on


and


<qtdebug.cc>
DEFUN("dbclear"...)
DEFUN("dbstop"...)
so on


and make the change in the Make file that says these files should be compiled, but not linked.  Could there be a way to instruct Octave at startup to "load" qtdialog.lo and qtdebug.lo?  For example, a file that contains of all the "libraries" to load?

The advantage of such an approach is that there are no callbacks and the interface is inherently called out by the definition of the Octave function, e.g., existing dbstop(filename,linenumber), errordlg(msg,...).  The person doing the GUI work (GTK, Qt, anything) can design things however they want inside those builtins so long as the interface meets the same format as the existing routines.  You wouldn't need to add anything to the core to interface with various GUIs, other than some elegant mechanism to load and replace functions in some function-table somewhere.

Dan Sebald <sebald>
Wed 03 Apr 2013 08:08:49 AM UTC, comment #12: 

Yes someone could write a qterrordlg() script file.  But just as easily someone could write an errordlg() script and override error dialogs.  In the case of the Java dialogs there is this routine "javaMethod" in the namespace that someone could override with a script file.

I've looked at the most recent setup for the GUI debugger.  There too are a number of new functions in the name space.  Doing "add" then tab-completion shows:


octave:6> add
add_dbclear_hook               add_pre_input_event_hook
add_dbstop_hook                addlistener
add_edit_hook                  addpath
add_enter_debugger_event_hook  addpref
add_exit_debugger_event_hook   addproperty
add_input_event_hook           adds/
add_post_input_event_hook      addtodate


Again, all functions that can be overridden.  What's more it overwhelms the user who types "add" tab-complete with an array of functions.

Picking the "dbstop" feature as an example, in the GUI code the


static octave_value_list
dbstop_hook_fcn (const octave_value_list& args, int)


is installed as the hook function via Fadd_dbstop_hook().  When that routine is called, it will do a simple relay of the "args" variable to:


  octave_link::update_breakpoint_hook_fcn (true, args);


(Clear uses "false" instead of "true".)  That routine in turn interprets the args, then apparently puts an event into:


              if (! error_state)
                {
                  event_listener->update_dbstop_marker (insert, file, line);
                  do_process_events ();
                }


That then does this:


octave_link::do_process_events (void)
{
  event_queue_mutex->lock ();

  gui_event_queue.run ();

  event_queue_mutex->unlock ();
}


At this point I'm going to stop trying to figure it out.  I can sort of guess.  There is something on the GUI thread side that is going to have to interpret that event in the queue and place a RedDot object of sorts in the editor sidebar.  That has to be done indirectly because the hook above is called from the Octave thread which cannot create GUI Qt objects, only non-GUI Qt objects.  So there is this event queue mechanism, which I hope is efficient and not some polling type of setup.

I think you'll agree that is getting quite convoluted.  And there is the extra work of having to define these callback functions.  Break points is an easy one.  Try expanding the idea to more advanced features.

It's just that it feels to me there should be a much more straightforward way.  I'll first address the debug breakpoint feature, then propose another way to incorporate variable GUI kits.

For the breakpoint set/clear, I'm imagining something quite simple using signals and slots.  First there is a Qt object similar to the dialog-creator I put in the patch.  Imagine for the time being the same setup as in the patch attached here, i.e., it is written in C++ and accessible to Octave core.  What I'm imagining is this debug_manager object emits a signal to its connected slot in the editor object, say something like


connect (debug_manager, request_reddot (QString& filename, int linenumber)
         file_editor, handle_reddot_request (QString& filename, int linenumber))


The debug_manager does


emit request_reddot (filename, linenumber);


That signal can go across threads.  The file_editor then creates a RedDot object and places it in the editor.  It also makes some connections like:


RedDot *reddot = new RedDot(...);
/* Put reddot in container class, etc. */
connect (debug_manager, remove_breakpoint (QString& filename, int linenumber),
         reddot, handle_remove_breakpoint (QString& filename, int linenumber));
connect (reddot, request_remove_breakpoint (QString& command),
         octave_link, command (QString& command));


After that, it is the signals bouncing back and forth that manage the behavior.  Say someone calls dbclear() at the command line.  That would cause debug_manager to


emit remove_breakpoint (filename, linenumber);


That signal would go to every RedDot slot that is connected to it--could be hundreds of slots connected to that signal.  Every RedDot would check if they are the one associated with filename and linenumber.  If so, close and destroy.

If the user points the mouse at the RedDot and clicks.  RedDot would


QString command;
command << "dbclear (""" << filename << """," << linenumber << ");"
emit request_remove_breakpoint (command);


That would go to the Octave thread, then Octave thread would run that command, if successful the debug_manager would emit the signal that goes back to the RedDot object slot and causes its removal.
        
I'll put comments about connecting Octave core and--for loss of better term--builtins in a followup post.

Dan Sebald <sebald>
Wed 03 Apr 2013 03:08:00 AM UTC, comment #11: 

I think you are misunderstanding what I mean when I say "hook/callback" functions.

What I am proposing is that instead of calling a function like "qterrdlg" directly, or by name using feval or eval, an equivalent function would be called through a function handle.  The function handle is installed by the GUI, so Octave itself does not have to know anything about the name of the function.  All Octave must do is make the function call if the function handle is defined.

This approach has nothing to do with Qt slots and signals and does not conflict with using them.

Even if a function is built in, a user could accidentally have a function calld qterrdlg in the path so that the built-in function won't be called.

It's not impossible to screw things up if we call these functions through callbacks, but it seems it would be somewhat harder to do.

John W. Eaton <jwe>
Group administrator
Wed 03 Apr 2013 01:12:31 AM UTC, comment #10: 


> Also, I noticed that you reimplemented the code that validates function arguments in C++. Why not keep that in the .m files and just implement the core dialog funtionality in C++, similar to what was done with the java-based code?


I didn't look at the Java code...until just now.  Yes, I suppose a hybrid would work.  Certainly I could have used something like "isinteger()".  On the other hand, I like programming in C++.  The Octave class library is set up very similar to the standard library, and Qt has mimicked the standard library as well.  It's to the point where I can almost guess at the member function name and it's there.  Even in retrospect I suppose I'd prefer just C++ or just script code rather than coordinate the two.  On the other hand, the hybrid at least allows some tweaking of the documentation without having to recompile.

Dan Sebald <sebald>
Wed 03 Apr 2013 12:52:54 AM UTC, comment #9: 

I missed a comment:  As for the eval/feval issue, that one doesn't seem like too much of a problem.

If one builds Qt gui as part of Octave, then qterrordlg, etc. are built in.  There is no way of messing up the path.

I'm not real familiar with the fltk interface.  But it should be possible to have fltk GUI ensure it can find the script files and make sure that location is part of the search path.  If fltk can't find its supporting files, it could post a pop-up dialog "Cannot find supporting script files.  The GUI will not function fully without them."  After that if someone does try using a command without a script, Octave will give a fairly coherent error, e.g., "error: `gtkerrordlg' undefined".

Keep thinking I guess...  The callback flow is fine, it's just that Qt prefers to not use them:

http://qt-project.org/doc/qt-4.8/signalsandslots.html

Dan Sebald <sebald>
Wed 03 Apr 2013 12:40:22 AM UTC, comment #8: 

OK, I'll take a look at it.  This is another thing that using a function pointer would avoid because we wouldn't be adding any visible functions to the libgui directory.  We might want to do that in the future, but I don't think that it is necessary now.

Also, I noticed that you reimplemented the code that validates function arguments in C++.  Why not keep that in the .m files and just implement the core dialog funtionality in C++, similar to what was done with the java-based code?

John W. Eaton <jwe>
Group administrator
Wed 03 Apr 2013 12:34:36 AM UTC, comment #7: 

Correct.  That's the only way I could move forward though.  The code that interprets the built-in functions resides in the Make of the libinterp directory.  It looks for intermediate files in its subdirectories, not elsewhere.  libgui is at the same level as libinterp.  If that Make code for generating intermediate files were at the base directory, then the dependence could be removed.

The good thing is that the dependence is only intermediate files.  But yes, gui code should not have its intermediate files over in the libinterp directory.  Make code is a big undertaking for me, that's why I was hoping one of the main developers could restructure that.

Actually, my preference would be to get rid of intermediate files.  Touching one of the builtin .cc files causes a big link process.  (Usually it is touching .h files that causes a ripple effect.)  However, I'm not expecting that much.

Dan Sebald <sebald>
Tue 02 Apr 2013 11:59:44 PM UTC, comment #6: 

I just noticed that the patch adds ../libgui things in libinterp.  I don't think we should do that.  It's importatnt that the libinterp directory not depend on anything in the libgui diretory.

John W. Eaton <jwe>
Group administrator
Tue 02 Apr 2013 11:33:57 PM UTC, comment #5: 

I would prefer to avoid eval (even feval), or even checking whether the GUI is running or what its name is at all.  Using the loadpath makes it too easy to get the wrong function if the path is screwed up.  That's why I prefer the hook function approach.  It avoids all these problems.

John W. Eaton <jwe>
Group administrator
Tue 02 Apr 2013 10:55:15 PM UTC, comment #4: 

Or, better still, overload is_gui_running as follows:

int is_gui_running (void);
std::string is_gui_running (std::string);

where the latter works as follows:

std:string f = is_gui_running ("errordlg");

returns "qterrordlg" (or "gtkerrordlg") if the GUI is running, "" otherwise.

Then one could simplify to

if (is_gui_running ())
  eval(is_gui_running ("errordlg"))
end

Dan Sebald <sebald>
Tue 02 Apr 2013 10:19:09 PM UTC, comment #3: 

Yes, this is why I didn't endeavor to start adding script files.

Another reason for the "is_gui_running" check inside the builtins is for when someone tries calling the routines without the GUI present.  (Try the commands launching with --no-gui.)

Well, there are a number of ways one could go.

1. A set of scripts for "errordlg", etc. that is installed particular to how Octave is launched.

2. Or, here's an idea I like.  Recall I wondered if we could make the "is_gui_running" test be more informative about which gui is running.  The "errordlg" command and associates could be made very general in C++ code with something like:

std::string guiname = is_gui_running ();
if guiname.empty ()
  error("must be running a GUI system for this command")
  return
else
  std::string function_name;
  function_name << guiname << "errordlg"
  call function_name
end

Dan Sebald <sebald>
Tue 02 Apr 2013 09:52:27 PM UTC, comment #2: 

Thanks for working on these functions.  We definitely need something in Qt to do this job for the Qt GUI.

I'm not sure what your thoughts are for using these functions to provide the errordlg, helpdlg, etc. functions that users will actually be calling, but I'd prefer to avoid having errordlg doing something like


  if (qt_gui)
    qterrordlg (..);
  elseif (gtk_gui)
    gtkerrordlg (..);
  else
    ...
  endif


because that means that a new GUI has to go find all those functions and insert a new case.  That's why I've been adding hooks/callbacks that the GUI can install.  Then a new GUI simply needs to install a list of function pointers and no other code needs to change.

Also, if these functions are not accessible unless the GUI installs them as hook/callback functions, then there is no need for any "is_the_gui_running" check because the only way the function pointers will be installed is if the GUI is running.

In any case, I think we should install this changeset since it is a good starting point.

John W. Eaton <jwe>
Group administrator
Tue 02 Apr 2013 06:23:37 AM UTC, comment #1: 

No change in code, just modification to five lines of comments that initially weren't included because of an mercurial rollback.  The octave-qtdialogs-2013apr02.patch file is a complete changeset.

(file #27744)

Dan Sebald <sebald>
Mon 01 Apr 2013 10:58:12 PM UTC, original submission:  

Attached is a patch that creates Qt dialogs similar to errordlg and so on.  There is also an attached script file to illustrate and test all the different input scenarios.

I've created the equivalent to the script files in the scripts/java subdirectory, using the same documentation from those files for the time being.  I've tried to make the behavior the same in terms of the order of button, input box placement.  The names simply have a "qt" prefix:

qterrordlg
qthelpdlg
qtwarndlg
qtmsgbox
qtquestdlg
qtlistdlg
qtinputdlg

I didn't recreate the dlgtest.m routine because I feel that function should remain as a script file so that it gives examples of how to use the code for the user.  My thinking is to incorporate Qt into dlgtest.m is to uses "eval" and prefix "qt" in the appropriate places based on conditions.  It should be very easy given the "isguirunning()" command.  Also, I didn't want to start including script files related to GUI just yet. This is sort of the first instance of GUI-related builtins, so one step at a time.

Some comments:

1. The documentation is the same as that for the Java versions, with slight adjustment.  Those files are listed Copyright 2010 Martin Hepperle, so I'm not sure what the copyright info should be for the new qt equivalents.  Code is all new, but copyright often extends generally to written material.

2. The communication uses a mutex/wait-condition to suspend the Octave thread while the user responds.  This is the way the Java dialog boxes operate.  The user's response will wake up the Octave thread.  The obvious result is that the command-line window is frozen even though the rest of the GUI is accessible (not bad).

3. The ramification of 2 is the limited nature of the dialog boxes. First step, I suppose.  But, I don't think Octave/GUI interaction is currently setup well enough to run nonmodal dialog windows.

4. My goal was to keep any GUI related items in the "libgui" subdirectory. However, the "make" process is currently set up to have builtins under the "libinterp" subdirectory.

5. I haven't in any way altered code within the core to accommodate this.  Not all the code in dialog.cc is run as part of the Octave thread.  Some of it is run as part of the GUI thread.

6. Whenever I could, I set up the widget code suitable for non-modal behavior...even though that could be down the road and there might likely be a different paradigm.  In other words, these dialogs would be a good start for something more sophisticated.

7. I left notes, // SHOULD CHECK IS INTEGER in the code.  I want to reproduce the following behavior in some simple way:

octave:5> x = [1:5]; x(2.5)
error: subscript indices must be either positive integers or logicals

I know that gripe_invalid_index() generates that message, but I'm wondering if there is some single line instruction that will do the test.

8. I left out the icon for the qtlistdlg() and qtinputdlg() routines. Having a question mark next to the list doesn't necessarily make sense, nor does it look that good and it takes up a lot of space.  I like the qtlistdlg without the icon.  I can add it easily enough.  I'm pretty certain no one will want a question mark icon.

9. The qtquestdlg() has the button order button1 | button2 | button3 on Gnome.  However, I've had to use a transmutation of the button roles to do this.  Different platforms may have different button orders, so things might be backward on other systems.  I've tried being tricky by assigning all the buttons the same role, but Qt gets confused by that. I could easily write a custom dialog that maintains the same button order on all systems, but I'd rather give the QMessageBox a try first. Qt is trying to think more in terms of a button's role so that it can adapt to all the various UI's out there.  Maybe that is what the questdlg() should be doing anyway.  Let's see how that pans out.

10. I used the "isguirunning ()" function to prevent the qt dialogs from signaling and then waiting for a signal that will never arrive.  Might we want to make "isguirunning ()" more informative by specifying what gui is running?  E.g., "qt" or "qt-4.0", or some other toolkit.

11. There is a FIXME in dialog.h, but that one isn't my fault.

Dan Sebald <sebald>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #27953:  octave-waitcondition_test-2013apr26.diff added by sebald (12KiB - application/octet-stream)
file #27954:  wctest.m added by sebald (339B - application/vnd.wolfram.mathematica.package)
file #27927:  octave-dialog_fixes-2013apr22.patch added by sebald (43KiB - application/octet-stream)
file #27917:  octave-dialog_fixes-2013apr21.patch added by sebald (43KiB - application/octet-stream)
file #27744:  octave-qtdialogs-2013apr02.patch added by sebald (54KiB - application/octet-stream)
file #27740:  octave-qtdialogs-2013apr01.patch added by sebald (54KiB - application/octet-stream)
file #27741:  qtdialogdem.m added by sebald (3KiB - application/vnd.wolfram.mathematica.package)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by jwe (Posted a comment)
  • -email is unavailable- added by sebald (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.

     

    Follow 9 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2013-09-04 rik5 StatusNone Done
        Open/ClosedOpen Closed
    2013-04-26 sebald Attached File- Added octave-waitcondition_test-2013apr26.diff, #27953
        Attached File- Added wctest.m, #27954
    2013-04-22 sebald Attached File- Added octave-dialog_fixes-2013apr22.patch, #27927
    2013-04-21 sebald Attached File- Added octave-dialog_fixes-2013apr21.patch, #27917
    2013-04-02 sebald Attached File- Added octave-qtdialogs-2013apr02.patch, #27744
    2013-04-01 sebald Attached File- Added octave-qtdialogs-2013apr01.patch, #27740
        Attached File- Added qtdialogdem.m, #27741

    Back to the top

    Powered by Savane 3.13-f8d8.
    Corresponding source code