Seems to be down to the focuschanged event i'm using to bar the focus changes. It's triggered by killing the mdi widget which contains my pseudo dialog, which then causes the focus to change again rather than the cleanup for the dialog being triggered correctly.
Now, what i really need then is for a widget to know when it's parent and therefore it are in the process of being hidden, but i cant see how to access this. Any ideas?
Thanks,
Richard.
Added after 6 minutes:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui>
#include <QMainWindow>
{
Q_OBJECT
public:
explicit MainWindow
(QWidget *parent
= 0);
~MainWindow();
private:
QMdiArea *mdiArea;
};
#endif // MAINWINDOW_H
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui>
#include <QMainWindow>
class MainWindow : public QWidget
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
QMdiArea *mdiArea;
};
#endif // MAINWINDOW_H
To copy to clipboard, switch view to plain text mode
mainwindow.cpp
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
MainWindow w;
w.show();
return a.exec();
}
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
To copy to clipboard, switch view to plain text mode
ctabmodaldialog.h
#ifndef CTABMODALDIALOG_H
#define CTABMODALDIALOG_H
//---------------------------------------------------------------------------------------
#include <QtGui>
//---------------------------------------------------------------------------------------
class CBlankWindow
: public QWidget{
Q_OBJECT
friend class CTabModalDialog;
{
this->parent = parent;
//this->setAttribute(Qt::WA_DeleteOnClose, true);
this->setMouseTracking(true);
this->setGeometry(parent->contentsRect());
this->show();
startime
= QDateTime::currentMSecsSinceEpoch();
}
virtual ~CBlankWindow()
{
}
{
qreal progress
= (qreal
)(QDateTime::currentMSecsSinceEpoch() - startime
) / 333.0;
progress = qMin(1.0, progress);
//Resize to cover parent.
this->setGeometry(parent->contentsRect());
p.setOpacity(0.75 * progress);
p.fillRect(this->rect(), Qt::black);
if(progress < 1.0)
QTimer::singleShot(33,
this,
SLOT(update
()));
}
{
hbl->insertWidget(0, widget, 0, Qt::AlignCenter);
}
protected:
//Eat events so thay are not passed onto the dimmed widgets below...
{
event->accept();
}
{
event->accept();
}
{
event->accept();
}
{
event->accept();
}
virtual void keyReleaseEvent
(QKeyEvent *event
) {
event->accept();
}
qint64 startime;
};
//---------------------------------------------------------------------------------------
class CTabModalDialog
: public QWidget{
Q_OBJECT
public:
explicit CTabModalDialog
(QWidget *parent
);
virtual ~CTabModalDialog();
// make sure you call this base after any showdialog setup in derived classes
virtual int ShowDialog( );
protected:
private:
CBlankWindow *bw;
int result;
bool bClosing;
signals:
void finished();
public slots:
void ACCEPT();
void REJECT();
};
//---------------------------------------------------------------------------------------
class CTabModalMessageBox : public CTabModalDialog
{
public:
private:
int result;
};
#endif // CTABMODALDIALOG_H
#ifndef CTABMODALDIALOG_H
#define CTABMODALDIALOG_H
//---------------------------------------------------------------------------------------
#include <QtGui>
//---------------------------------------------------------------------------------------
class CBlankWindow : public QWidget
{
Q_OBJECT
friend class CTabModalDialog;
CBlankWindow(QWidget* parent)
:QWidget(parent)
{
this->parent = parent;
//this->setAttribute(Qt::WA_DeleteOnClose, true);
this->setMouseTracking(true);
this->setGeometry(parent->contentsRect());
this->show();
startime = QDateTime::currentMSecsSinceEpoch();
hbl = new QHBoxLayout(this);
}
virtual ~CBlankWindow()
{
}
virtual void paintEvent(QPaintEvent *event)
{
QPainter p(this);
qreal progress = (qreal)(QDateTime::currentMSecsSinceEpoch() - startime) / 333.0;
progress = qMin(1.0, progress);
//Resize to cover parent.
this->setGeometry(parent->contentsRect());
p.setOpacity(0.75 * progress);
p.fillRect(this->rect(), Qt::black);
if(progress < 1.0)
QTimer::singleShot(33, this, SLOT(update()));
QWidget::paintEvent(event);
}
void SetWidget(QWidget* widget)
{
widget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
hbl->insertWidget(0, widget, 0, Qt::AlignCenter);
}
protected:
//Eat events so thay are not passed onto the dimmed widgets below...
virtual void mouseMoveEvent(QMouseEvent *event)
{
event->accept();
}
virtual void mousePressEvent(QMouseEvent *event)
{
event->accept();
}
virtual void mouseReleaseEvent(QMouseEvent *event)
{
event->accept();
}
virtual void keyPressEvent(QKeyEvent *event)
{
event->accept();
}
virtual void keyReleaseEvent(QKeyEvent *event)
{
event->accept();
}
QHBoxLayout *hbl;
qint64 startime;
QWidget* parent;
};
//---------------------------------------------------------------------------------------
class CTabModalDialog : public QWidget
{
Q_OBJECT
public:
explicit CTabModalDialog(QWidget *parent);
virtual ~CTabModalDialog();
// make sure you call this base after any showdialog setup in derived classes
virtual int ShowDialog( );
protected:
virtual void paintEvent(QPaintEvent*);
virtual void closeEvent(QCloseEvent *event);
QEventLoop l;
private:
CBlankWindow *bw;
int result;
bool bClosing;
signals:
void finished();
public slots:
void focusChanged(QWidget* from, QWidget * toWidget);
void ACCEPT();
void REJECT();
};
//---------------------------------------------------------------------------------------
class CTabModalMessageBox : public CTabModalDialog
{
public:
static int ShowDialog(QString title, QString text, QPixmap icon, QWidget* parent, bool ok_button = true, bool cancel_button = false);
private:
int result;
CTabModalMessageBox(QString title, QString text, QPixmap icon, QWidget* parent, bool ok_button = true, bool cancel_button = false);
};
#endif // CTABMODALDIALOG_H
To copy to clipboard, switch view to plain text mode
ctabmodaldialog.cpp
#include "ctabmodaldialog.h"
//---------------------------------------------------------------------------------------
CTabModalDialog
::CTabModalDialog(QWidget *parent
): QWidget( parent,Qt
::Popup|Qt
::Dialog) {
this->bClosing = false;
this->setFocus();
bw = new CBlankWindow(parent);
bw->SetWidget(this);
this->show();
this->raise();
this->setAttribute(Qt::WA_DeleteOnClose,false);
}
{
if ( isAncestorOf(from))
{
if (!isAncestorOf(to)&& !this->bClosing)
{
QWidget * widget
= dynamic_cast<QWidget
* >
(from
);
// if this is being hidden we need to not do this!
if ( widget)
widget->setFocus(Qt::OtherFocusReason);
}
}
// else do nothing
}
///
/// On destruction remove event filters. RAF 12/7/13
///
CTabModalDialog::~CTabModalDialog()
{
this->bClosing = true;
// disconnect(qApp,SIGNAL(focusChanged(QWidget*,QWidget*)),this,SLOT(focusChanged(QWidget*,QWidget*)));
// disconnect (this,SIGNAL(finished()),&l,SLOT(quit()));
bw->hide();
bw->deleteLater();
}
{
p.setBrush(brush);
p.drawRoundedRect(this->rect(), 5, 5);
}
//---------------------------------------------------------------------------------------
{
this->bClosing = true;
bw->hide();
bw->close();
}
//---------------------------------------------------------------------------------------
int CTabModalDialog::ShowDialog( )
{
this->show();
this->raise();
this->setFocus();
this->activateWindow();
connect (this,SIGNAL(finished()),&l,SLOT(quit()),Qt::QueuedConnection);
l.exec();
this->bClosing = true;
this->hide();
return this->result;
}
void CTabModalDialog::ACCEPT()
{
this->bClosing = true;
this->finished();
}
void CTabModalDialog::REJECT()
{
this->bClosing = true;
this->finished();
}
{
CTabModalMessageBox * mb = new CTabModalMessageBox(title,text,icon,parent,ok_button,cancel_button);
return (static_cast<CTabModalDialog*>(mb))->ShowDialog();
}
:CTabModalDialog(parent)
{
hbl->setAlignment(Qt::AlignLeft);
page_icon->setPixmap(icon);
hbl->addWidget(page_icon);
QFont font
= page_text
->font
();
font.setPointSize(16);
page_text->setFont(font);
hbl->addWidget(page_text);
line
->setGeometry
(QRect(50,
40,
641,
16));
line
->setFrameShape
(QFrame::HLine);
line
->setFrameShadow
(QFrame::Sunken);
vbl->addLayout(hbl);
vbl->addWidget(line);
lbl_txt->setWordWrap(true);
vbl->addWidget(lbl_txt);
vbl->addLayout(hbl2);
if(ok_button)
{
connect(btn_ok, SIGNAL(clicked()), this, SLOT(ACCEPT()));
hbl2->addWidget(btn_ok);
}
if(cancel_button || (!(ok_button | cancel_button)))
{
connect(btn_cancel, SIGNAL(clicked()), this, SLOT(REJECT()));
hbl2->addWidget(btn_cancel);
}
this->setLayout(vbl);
this->show();
this->raise();
this->activateWindow();
}
#include "ctabmodaldialog.h"
//---------------------------------------------------------------------------------------
CTabModalDialog::CTabModalDialog(QWidget *parent):
QWidget( parent,Qt::Popup|Qt::Dialog)
{
this->bClosing = false;
this->setFocus();
bw = new CBlankWindow(parent);
bw->SetWidget(this);
this->show();
this->raise();
this->setAttribute(Qt::WA_DeleteOnClose,false);
connect(qApp,SIGNAL(focusChanged(QWidget*,QWidget*)),this,SLOT(focusChanged(QWidget*,QWidget*)));
}
void CTabModalDialog::focusChanged(QWidget* from , QWidget* to)
{
if ( isAncestorOf(from))
{
if (!isAncestorOf(to)&& !this->bClosing)
{
QWidget * widget = dynamic_cast<QWidget * >(from);
// if this is being hidden we need to not do this!
if ( widget)
widget->setFocus(Qt::OtherFocusReason);
}
}
// else do nothing
}
///
/// On destruction remove event filters. RAF 12/7/13
///
CTabModalDialog::~CTabModalDialog()
{
this->bClosing = true;
// disconnect(qApp,SIGNAL(focusChanged(QWidget*,QWidget*)),this,SLOT(focusChanged(QWidget*,QWidget*)));
// disconnect (this,SIGNAL(finished()),&l,SLOT(quit()));
bw->hide();
bw->deleteLater();
}
void CTabModalDialog::paintEvent(QPaintEvent *)
{
QPainter p(this);
QBrush brush(this->palette().color(QPalette::Base));
p.setBrush(brush);
p.drawRoundedRect(this->rect(), 5, 5);
}
//---------------------------------------------------------------------------------------
void CTabModalDialog::closeEvent(QCloseEvent *event)
{
this->bClosing = true;
bw->hide();
bw->close();
QWidget::closeEvent(event);
}
//---------------------------------------------------------------------------------------
int CTabModalDialog::ShowDialog( )
{
this->result = QDialog::Rejected;
this->show();
this->raise();
this->setFocus();
this->activateWindow();
connect (this,SIGNAL(finished()),&l,SLOT(quit()),Qt::QueuedConnection);
l.exec();
this->bClosing = true;
this->hide();
return this->result;
}
void CTabModalDialog::ACCEPT()
{
this->result = QDialog::Accepted;
this->bClosing = true;
this->finished();
}
void CTabModalDialog::REJECT()
{
this->result = QDialog::Rejected;
this->bClosing = true;
this->finished();
}
int CTabModalMessageBox::ShowDialog(QString title, QString text, QPixmap icon, QWidget* parent, bool ok_button, bool cancel_button )
{
CTabModalMessageBox * mb = new CTabModalMessageBox(title,text,icon,parent,ok_button,cancel_button);
return (static_cast<CTabModalDialog*>(mb))->ShowDialog();
}
CTabModalMessageBox::CTabModalMessageBox(QString title, QString text, QPixmap icon, QWidget* parent, bool ok_button, bool cancel_button )
:CTabModalDialog(parent)
{
result = QDialog::Rejected;
QVBoxLayout* vbl = new QVBoxLayout(this);
QHBoxLayout* hbl = new QHBoxLayout;
hbl->setAlignment(Qt::AlignLeft);
QLabel *page_icon = new QLabel(this);
page_icon->setPixmap(icon);
page_icon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
hbl->addWidget(page_icon);
QLabel* page_text = new QLabel(title, this);
QFont font = page_text->font();
font.setPointSize(16);
page_text->setFont(font);
page_text->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
hbl->addWidget(page_text);
QFrame* line = new QFrame(this);
line->setGeometry(QRect(50, 40, 641, 16));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
vbl->addLayout(hbl);
vbl->addWidget(line);
QLabel* lbl_txt = new QLabel(text, this);
lbl_txt->setWordWrap(true);
vbl->addWidget(lbl_txt);
QHBoxLayout* hbl2 = new QHBoxLayout;
vbl->addLayout(hbl2);
if(ok_button)
{
QPushButton* btn_ok = new QPushButton(tr("Ok"), this);
connect(btn_ok, SIGNAL(clicked()), this, SLOT(ACCEPT()));
hbl2->addWidget(btn_ok);
}
if(cancel_button || (!(ok_button | cancel_button)))
{
QPushButton* btn_cancel = new QPushButton(tr("Cancel"), this);
connect(btn_cancel, SIGNAL(clicked()), this, SLOT(REJECT()));
hbl2->addWidget(btn_cancel);
}
this->setLayout(vbl);
this->show();
this->raise();
this->activateWindow();
}
To copy to clipboard, switch view to plain text mode
mymdiwindow.h
#ifndef MYMDIWINDOW_H
#define MYMDIWINDOW_H
#include <QMdiSubWindow>
#include <QtGui>
class myMDIWindow : public QMdiSubWindow
{
Q_OBJECT
public:
explicit myMDIWindow
(QWidget *parent
= 0);
virtual ~myMDIWindow();
public slots:
void popup();
};
#endif // MYMDIWINDOW_H
#ifndef MYMDIWINDOW_H
#define MYMDIWINDOW_H
#include <QMdiSubWindow>
#include <QtGui>
class myMDIWindow : public QMdiSubWindow
{
Q_OBJECT
public:
explicit myMDIWindow(QWidget *parent = 0);
virtual ~myMDIWindow();
QPushButton *btnPopup;
public slots:
void popup();
};
#endif // MYMDIWINDOW_H
To copy to clipboard, switch view to plain text mode
mymdiwindow.cpp
#include "mymdiwindow.h"
#include "ctabmodaldialog.h"
myMDIWindow
::myMDIWindow(QWidget *parent
) : QMdiSubWindow(parent)
{
this->setMinimumSize(400,400);
lytMain->addWidget(btnPopup);
this->setLayout(lytMain);
connect(btnPopup,SIGNAL(clicked()),this,SLOT(popup()));
}
myMDIWindow::~myMDIWindow()
{
foreach
(QObject* o, this
->children
()) {
QWidget*w
= dynamic_cast<QWidget
*>
(o
);
if (w)
w->hide();
}
}
void myMDIWindow::popup()
{
CTabModalMessageBox
::ShowDialog("blah",
"blah",
QPixmap(10,
10),
this,
true,
true);
}
#include "mymdiwindow.h"
#include "ctabmodaldialog.h"
myMDIWindow::myMDIWindow(QWidget *parent) :
QMdiSubWindow(parent)
{
this->setMinimumSize(400,400);
btnPopup = new QPushButton("PopUp",this);
QVBoxLayout * lytMain = new QVBoxLayout(this);
lytMain->addWidget(btnPopup);
this->setLayout(lytMain);
connect(btnPopup,SIGNAL(clicked()),this,SLOT(popup()));
}
myMDIWindow::~myMDIWindow()
{
foreach(QObject* o, this->children())
{
QWidget*w = dynamic_cast<QWidget*>(o);
if (w)
w->hide();
}
}
void myMDIWindow::popup()
{
CTabModalMessageBox::ShowDialog("blah","blah",QPixmap(10,10),this,true,true);
}
To copy to clipboard, switch view to plain text mode
To reproduce, Click one of the popup buttons and then close the containings mdi widget.
Bookmarks