PDA

View Full Version : QMessageBox that blocks only the current QMdiSubWindow?



dv8
31st January 2013, 15:40
Here is another question that I was not able to answer myself or find a solution in the net...
I'm working with QMdiArea and I have multiple tabs opened (web browser like application). I'm trying to display a message box in a single tab, in a way that it does not block the whole application, but only blocks the parent widget (the current tab/QMdiSubWindow). This message box should not block the other tabs and the user should be able to switch to another tab, even if the message box in the current tab is still opened.
What I have tried so far is:


QMessageBox *box=new QMessageBox(qobject_cast<QWidget *>(parent())); //The cast here produces a pointer to my custom widget, which is contained in the tab/QMdiSubWindow.
box->setAttribute(Qt::WA_DeleteOnClose);
box->setStandardButtons(QMessageBox::Ok);
box->setWindowModality(Qt::WindowModal); //setting modality to Qt::NonModal does not lock the current tab, so it is not a solution
box->setWindowTitle("Message:");
box->setText("My test message.");
connect(box,SIGNAL(destroyed()),this,SLOT(Continue ()));
box->show();


The description of the Qt::WindowModal constant says:


The window is modal to a single window hierarchy and blocks input to its parent window, all grandparent windows, and all siblings of its parent and grandparent windows.

and if I understand it correctly, "...parent window, all grandparent windows, and all siblings of its parent and grandparent windows", basically means the whole application. :( And that's what happens in reality - it blocks the whole application, just like Qt::ApplicationModal.
I'm tackling this for a few hours now and I feel frustrated. Can someone please give any other ideas how I can achieve my goal???

Santosh Reddy
31st January 2013, 15:51
basically means the whole application. And that's what happens in reality - it blocks the whole application, just like Qt::ApplicationModal.
An Application can also be multi window application, (e.g. 2 QMainWindows), in such case only the window in which the QMessageBox is will be blocked, and the other window can still be operated on.

You cannot use standard QMessageBox to achieve what you wanted.

A standard QMessageBox may not be a good solution, as it is a top level window (independent Dialog), you will need somthing which will not be shown when other tabs are selected. For that it will be better solution to show a custom message-widget over the tab page widget (not adding it in layout), and paint it over the rest of the siblings, and obviously manually setting the message-widget position

dv8
31st January 2013, 21:17
Thanks Santosh, for the insights!
I'm currently trying to implement your idea and it is working nicely, but there is one issue I can't get passed. :(
I have made the following simple class:


namespace Ui {
class MyMessageBox;
}

class MyMessageBox : public QWidget
{
Q_OBJECT

public:
explicit MyMessageBox(QWidget *parent = 0, QString Title="Message box", QString Content="");
~MyMessageBox();

private:
Ui::MyMessageBox *ui;
};

which visually resembles the original message box. It contains an Icon, a label to display the message in and an OK button.

What I'm doing to visualize it is:


MyMessageBox *msg=new MyMessageBox(*MyCustomTabWidget,Title,Message);
connect(msg,SIGNAL(destroyed()),this,SLOT(Continue ()));
msg->setAttribute(Qt::WA_DeleteOnClose);
msg->setWindowFlags(Qt::SubWindow); //I've found that Qt::SubWindow flag is giving me the desired behavior
msg->show();
msg->raise();

This message box is displayed over a QWebView which takes almost all the MyCustomTabWidget space. However, when it is displaying only the Icon, the Message text and the OK button are visible over the QWebView widget. The body and the title bar are not visible. :( I've made countless tests with different window flags, but nothing seams to help. Any suggestions, why this is happening and how I can fix it?

dv8
1st February 2013, 09:55
OK, I've moved the attributes and flags lines in the constructor, so here is what I have now:


#include "mymessagebox.h"
#include "ui_mymessagebox.h"
MyMessageBox::MyMessageBox(QWidget *parent,QString Title,QString Content) :
QWidget(parent),
ui(new Ui::MyMessageBox)
{
ui->setupUi(this);
this->setAttribute(Qt::WA_DeleteOnClose);
this->setWindowFlags(Qt::SubWindow | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowStaysOnTopHint);
this->setWindowTitle(Title);
ui->labelMessage->setText(Content);
this->show();
this->move(50,50);
}
MyMessageBox::~MyMessageBox()
{
delete ui;
}


I'm creating the widget like this:


MyMessageBox *msg=new MyMessageBox(*MyCustomTabWidget,"Title","Message");

And here is what I see:
8665
I added a QFframe container with border (for testing purposes) and that border is seen on the picture. Without the QFrame no border is displayed and only the Icon, the Text and the OK button are visible.
Please, anyone, I need some hints about what is causing this issue and any suggestions how can I fix it.

Santosh Reddy
1st February 2013, 10:59
I don't think you can get title bar, and window frame. I think you may need to draw them manually, but wait I not 100% sure of this, so wait and see someone else has anything for you.

wysota
1st February 2013, 12:00
One can use the same code QMdiSubWindow uses to render its frame.

dv8
1st February 2013, 12:25
This thought crossed my mind too, but I didn't want to over-complicate it, so I came up with a workaround. I added the message frame in my "MyCustomTabWidget" above the QWebView (that is visible on the screenshot) and hid it. Then, whenever I need to display a message, I set the text and un-hide the QFrame. This brings the QWebView down and my message widget is displayed at the top, which works perfectly for me. :) When the OK button is pressed, the message frame is set to hidden again and everything comes into place.
Here is how it looks now:
8666
I used a label with lightblue background color to make a kind of title for my message box. It still needs a little visual refinement, but the important thing is that it does what I want. :)
Thank you both for your assistance.