[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Debugging and the GUI Editor; Qt help needed
From: |
Daniel J Sebald |
Subject: |
Re: Debugging and the GUI Editor; Qt help needed |
Date: |
Thu, 28 Mar 2013 14:00:34 -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 03/28/2013 01:21 PM, John W. Eaton wrote:
On 03/28/2013 02:08 PM, Daniel J Sebald wrote:
On 03/28/2013 02:43 AM, John W. Eaton wrote:
It would be helpful if people could test these new features. There is no
need to report the problems I've listed above, but if you find other
things that don't work correctly, let me know. Or if you'd just like to
say, "Wow, these new features look awesome!" that would be fine too.
I haven't compiled and run yet, so I assume it looks awesome.
I looked at the code, though, e.g.,
http://hg.savannah.gnu.org/hgweb/octave/rev/389b09a914e2
and I would suggest that we try to not introduce callbacks in the way
you have done. The problem with the callbacks is it is connecting two
threads with functions. We should be using the Qt signal/slot mechanism
across threads. Otherwise there is a good chance we're unnecessarily
restricting capabilities and possibly making programming more difficult
down the road.
Then can you please provide an example that shows how to do that for one
of these cases? I don't mind changing the way things are done if it
really does make a difference, but I need some pointers here as I'm
almost clueless about the proper way to do Qt programming. Just saying
"use signals/slots" doesn't help me much.
This evening and tomorrow I can clean up the code I have and create a
patch. I think it is easiest to work from a diff file. But for the
time being here are a few lines to illustrate, and I'm sure it will be
clearer with the whole changeset to follow:
IN THE OCTAVE THREAD
I've written some builtin routines that really don't touch core Octave
code. Instead, they act like a driver of sorts. e.g.,
// Signal GUI thread to put up simple message box using OK
// as the only button.
uiwidget_creator.signal_dialog (message, title, icon,
QStringList (),
QString (), QStringList ());
// Wait while the user is responding to message box.
waitcondition.wait (&mutex);
The above uiwidget_creator is just a basic class where I've organized
all the signals and slots. It is basically an "emit" with the same
input arguments as "signal_dialog()". I do that so that the data
transferred across threads can be stored in uiwidget_creator's object.
Anyway, you can see that the octave thread emits the signal, then
suspends itself, with no function call across to the GUI thread. Later
the thread is awaken with:
void
QUIWidgitCreator::dialog_finish_continue (int result)
{
// Store the value so that builtin functions can retrieve.
dialog_result = result;
// Wake up Octave process so that it continues.
waitcondition.wakeAll();
}
which is a slot that is accessed by the GUI thread emitting the
connected signal. The "result" is the data that the GUI thread is
sending. Pretty minimal in this case. After the "wakeAll", the Octave
thread continues right after the "waitcondition.wait (&mutex);" line in
the hunk above.
IN THE GUI THREAD
At startup, the main window makes the connections:
connect (&uiwidgit_creator, SIGNAL (create_dialog (const QString&,
const QString&, const QString&,
const QStringList&, const QString&,
const QStringList&)),
this, SLOT (handle_create_dialog (const QString&,
const QString&, const QString&,
const QStringList&, const QString&,
const QStringList&)));
so that the Octave thread can signal that it would like a QMessageBox
placed on the screen.
The "handle_create_dialog" slot in the GUI thread then does this, and it
makes connections between the message box it is creating and the slots
(analogous to callbacks) in the Octave thread.
// Create a dialog with specified string and connect to a wait condition
// to wake up thread.
void
main_window::handle_create_dialog (const QString& message, const
QString& title,
const QString& icon, const
QStringList& button,
const QString& defbutton,
const QStringList& role)
{
// Process all this stuff
// Create a NonModal message about error.
QMessageBox* msgBox = new QMessageBox (eicon, title, message, 0, 0);
connect (msgBox, SIGNAL (buttonClicked (QAbstractButton *)),
&uiwidgit_creator, SLOT (dialog_button_clicked
(QAbstractButton *)));
connect (msgBox, SIGNAL (finished (int)),
&uiwidgit_creator, SLOT (dialog_finish_continue (int)));
msgBox->show ();
You can guess that the slot on the Octave thread side
(dialog_finish_continue), is that small hunk of code that wakes up the
Octave thread. Whenever the button on the QMessageBox is pressed, it
signals the slot in the Octave thread that it is finished and gives it
the data.
SUMMARY
So, there isn't any function call across threads. This example is a
little more dynamic than what might be needed for the debugger because
the message box is created and then connections are made. In the
debugger case, maybe just the initial connections at startup would be
needed. What the example I give does do is it enables the use of the
Mutex and other similar concepts in Qt. That's the thing that could
prove beneficial down the line. Hard to say, but I just think that
remaining within the Qt paradigm as much as possible can only be good.
How might this play out in the debugger case? Well, one can be creative
and come up with different ways, but I can imagine that clicking a debug
tab issues a signal to some object in the Octave thread that then
disables the breakpoint in Octave core code. So on. These things are a
bit of trial and error for a while until everything falls in place and
then it is like, "I should have used that signal/slot sooner!".
Think in terms like this:
|
OCTAVE CORE <--> BUILTIN COMM OBJECT | GUI THREAD
|
and there are signals/slots across the thread.
Dan
- Re: Debugging and the GUI Editor; Qt help needed, (continued)
Re: Debugging and the GUI Editor; Qt help needed, Daniel J Sebald, 2013/03/28