PDA

View Full Version : Creating a Modeless Dialog that responds to a close event



kyue
29th May 2009, 15:47
Hello,

I'm currently trying to create a modeless dialog box (or QMessageBox) using Qt 4.3 that:

1. gets created in my Main class
2. when it closes, it will call another function in the Main class that will exit the program.

In other words, I am looking for a modeless dialog box that will perform an exit once the users closes the dialog box. I've looked at some posts on the internet and a few in this forum but I can't seem to figure out how to do it. This thread was a little helpful:

http://www.qtforum.org/post/53763/removing-modeless-dialog.html?highlight=modeless#post53763

where it gave the idea of connecting the destroyed() event to a slot, or reimplement closeEvent(). Here is a little portion of my code:


QMessageBox* pMessageBox = new QMessageBox(QMessageBox::Information,
QObject::tr("My Software"),
QObject::tr("Text in my dialog box."),
QMessageBox::Ok,
0,
Qt::Dialog | Qt::WindowStaysOnTopHint );

pMessageBox->setModal(false);
pMessageBox->show();
//pMessageBox->activateWindow();

//connect(pMessageBox, SIGNAL(closeEvent()), this, SLOT(exitApp()));
connect(pMessageBox, SIGNAL(destroyed()), this, SLOT(exitApp()));


But I don't seem to get the same result. The breakpoint in exitApp() never gets triggered.

I got a little excited when I saw documentation that you can set a flag in QMessageBox to make it modeless, but this was in another version of Qt and not in Qt 4.3.

Any ideas will be greatly appreciated.

Kat

MikeG
29th May 2009, 16:15
Connect the slot to something where you know you'll get output from (at least see if it's triggering). Does exitApp() when called on its own (without your connect) exit the application properly?

kyue
29th May 2009, 16:21
Hi Mike,

Thanks for your reply. Yes, exitApp() works properly and will exit the program. Here is function definition:



void CMainWindow::exitApp()
{
QApplication::exit(0);
}


I believe it has something to do with the events I'm limited to. I've read in a few places that modeless dialogs will only destroy itself (or emit the destoryed() signal) if a flag is set (Qt::WA_DeleteOnClose ... I think?) But I can't seem to find the right place in my constructor to add this flag. Maybe I'm just not doing it correctly...

In addition, the closeEvent() event doesn't work either...

Kat

aamer4yu
29th May 2009, 19:15
You could have also used -

connect(pMessageBox, SIGNAL(destroyed()), qApp, SLOT(quit()));

kyue
29th May 2009, 19:26
Thanks for your reply. Yes, this is true, however, it still doesn't work because I don't think the destroyed() signal is sent out for my application to catch it...

wysota
29th May 2009, 19:26
You forget that when you close a window, it doesn't get deleted. Use the WA_DeleteOnClose attribute to destoy a closed widget.

kyue
29th May 2009, 20:25
Thank you. I was a little lost at how I was suppose to set that attribute. After re-reading the documentation there is a function QWidget::setAttribute() available for use. It makes sense now...

Here it is just in case for anyone else out there who might need it :)



pMessageBox->setModal(false);
pMessageBox->setAttribute(Qt::WA_DeleteOnClose);
pMessageBox->show();
//pMessageBox->activateWindow();

//connect(pMessageBox, SIGNAL(closeEvent()), this, SLOT(exitApp()));
connect(pMessageBox, SIGNAL(destroyed()), this, SLOT(exitApp()));

wysota
30th May 2009, 01:19
One thing interests me in your code - what is your usecase of using a non-modal message box that terminates the application when closed? Message boxes are usually modal...

kyue
1st June 2009, 14:42
What happens is that the user is notified that the application will now close, through a dialog box. The code is written where the Main thread and UI thread are the same. Therefore, if I had a modal dialog box open and I needed the main thread to process an incoming message, the main thread waits and tries to obtain a mutex on the same thread and my program crashes. Therefore, I needed a modeless dialog box where it doesn't lock my main thread.

wysota
1st June 2009, 18:21
What do you mean by "main thread" and "ui thread"?

kyue
1st June 2009, 18:28
The "main thread" is the main application thread. "UI thread" is the thread that handles User Interface messages and processes them.

So I have 1 thread that will handle and process my main application operations as well as UI operations. In my situation, this 1 thread was sitting and waiting for my modal dialog box to close, while there was another request from the "main thread" that needed to be processed.

I hope that helped :)

wysota
1st June 2009, 18:37
So you have one or two threads in your application?

kyue
1st June 2009, 18:39
We have a few, but the UI thread is unfortunately sitting on the same thread as this main thread.

wysota
1st June 2009, 18:50
And where do those messages come from? Other threads or the same thread? What kind of events are they?

kyue
1st June 2009, 18:58
The messages come from the network (LAN). We have wrapper classes that we use that we call the DataChannel classes. These messages come in, the application receives it, processes it, and sends the request to the respectful handler.

So throughout our code, we use modeless dialog boxes so that the thread will be free to receive and process these DataChannel messages.

wysota
1st June 2009, 19:49
Socket notifiers might indeed be blocked when a dialog is executed but there is a way to override it if you want. You have to provide a method with exact same contents as exec() but with different parameters sent to QEventLoop::exec(). If you add clear the QEventLoop::ExcludeSocketNotifiers flag, you should get a modal dialog with network processing. The simplest implementation is to just create the event loop, set modality and call exec() on the event loop.

kyue
1st June 2009, 21:07
Thank you for your advice. I am currently working on a port from Windows->Mac and I am required to use the existing libraries and how it is currently written. We receive these messages in our wrapper classes and only 2% of them are Qt projects. So I was asked to find a modeless dialog box on Qt as a solution.

wysota
2nd June 2009, 10:18
I'm not telling you to modify Qt, just to provide an additional method that will re-enable socket notifiers.