Here is my solution:
I don't used setModal and something like that. Just show() and hide() the dialog and it should stay on top of it's parent. I added push and pop (like a stack) because different threads might be interested in showing/hiding the dialog... so it should be guaranteed that only the last call hides the dialog. Other solutions are welcome... this is just quick and dirty.
class WaitDialog : public QDialog
{
Q_OBJECT
public:
WaitDialog(const QString& message, QWidget *parent = 0);
public slots:
void show();
void hide();
void push();
void pop();
signals:
void visibilityChanged(bool enable);
private:
int stack;
QLabel* msgLabel;
};
WaitDialog::WaitDialog(const QString &message, QWidget *parent)
: QDialog(parent, Qt::FramelessWindowHint),
msgLabel(new QLabel(message, this)),
stack(0)
{
QVBoxLayout* mainLayout = new QVBoxLayout;
mainLayout->setContentsMargins(30, 30, 30, 30);
mainLayout->addWidget(msgLabel);
setLayout(mainLayout);
}
void WaitDialog::show()
{
QDialog::show();
emit visibilityChanged(true);
}
void WaitDialog::hide()
{
QDialog::hide();
emit visibilityChanged(false);
}
void WaitDialog::push()
{
stack++;
show();
emit visibilityChanged(true);
}
void WaitDialog::pop()
{
if (stack > 0)
--stack;
if (stack == 0)
{
hide();
}
}
So anything I do is just
connect(someObject, SIGNAL(someProcessingFinished()), waitDialog, SLOT(pop()));
to automatically hide the dialog and manually call waitDialog->push() when start processing (or wire it against some someProcessingStarted() method).
The dialog itself is instantiated this way:
WaitDialog* waitDialog = new WaitDialog(tr("Loading data... please wait."), this);
and got its parent in the second param (this in the example).
Works for me to let the main window pop up a message that stays as long as required to stop ui interaction but keeping the application running instead of waiting for the dialog to return. Not used modality flags etc. I just connected interested widgets to the visibilityChanged() signal emitted by the WaitDialog.
connect(waitDialog, SIGNAL(visibilityChanged(bool)), someControl, SLOT(doSomething(bool)));
... and for example the following code do disable/enable the control whenever the WaitDialog changes visibility...
void SomeControl::doSomething(bool enabled)
{
setEnabled(!enabled);
}
Look my question and answer here to get know how to keep it centered.