Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to use Qt without QApplication::exec()?

Is there a safe way to use Qt without calling QApplication::exec()?

I have a number of different objects that are carrying out long-lived processes on multiple resources (at least one of them is communicating with a web application server). I'm making a GUI application that prompts the user for input at the right time for these different processes. I'd like to have my 'flow' logic - the logic that determines what to do next - in one place and not in a GUI object like a dialog class. I was thinking that I could do something like this:

...

wait_dialog dlg;
dlg.setModal( false );
dlg.show(); // Should return...

netobject.start_long_lived_process_that_happens_on_other_thread( &completion_callback );
while ( !completion_callback_called() )
{
    qApp->processEvents();
    netobject.pump_callbacks();
    magically_avoid_busywait_while_still_servicing_qt_somehow();
}

dlg.hide();

...

Is this safe, from Qt's point of view? Is there a 'good' way of implementing magically_avoid_busywait_while_still_servicing_qt_somehow()?

What I'm trying to accomplish here is to write our processing flow in the most explicit way possible. I'd like a single function that does this:

 show_a_non_modal_wait_dialog()

 start_some_processing_1()

 wait_for_processing_1_to_finish()

 dismiss_non_modal_wait_dialog()

 show_modal_input_dialog()

 if ( cancelled ) return

 show_a_non_modal_wait_dialog()

 start_some_processing_2()

 wait_for_processing_2_to_finish()

 dismiss_non_modal_wait_dialog()

 show_modal_input_dialog()

 if ( cancelled ) return

 ...

What I really want to avoid is kicking off and waiting for the processing inside Qt widgets and windows. Also, the processing objects themselves are entirely independent of Qt. I suppose what I'm trying to do is create a controller in a single function with a few helper callbacks and status variables.

like image 479
Ted Middleton Avatar asked Oct 03 '12 23:10

Ted Middleton


1 Answers

What you want is an event loop other that the application's main event loop. This can be done using the QEventLoop:

wait_dialog dlg;
dlg.setModal( false );
dlg.show(); // Should return...

QEventLoop loop;
connect(&netobject, SIGNAL(done()), &loop, SLOT(quit()));
netobject.start_long_lived_process_that_happens_on_other_thread();

loop.exec(); // BLOCKING (non-busy) until quit() is called via the signal done()

While this is (in my eyes) clean code, this requires your netobject class to be a QObject and implement a signal done() (which is also cleaner than providing callbacks).

Now you can wrap this whole code in a function which will be a blocking call on itself, so it can return some results from your dialog if you want so.

like image 143
leemes Avatar answered Oct 29 '22 15:10

leemes