Pherrymason
Pherrymason

Reputation: 8067

Qt: How to know when a QMdiSubWindow is closed?

Is there any way I can get notified when a user closes a QMdiSubWindow? I cannot find any signal in QMdiArea nor in QMdiSubWindow that suggests I can.

I think my only chance is by subclassing QMdiSubWindow and overriding the close event, but is there any other way?

Upvotes: 6

Views: 6345

Answers (5)

Mitrakov Artem
Mitrakov Artem

Reputation: 1523

I had the same trouble, but in my case the task was more specific: "How to hide a subwindow when I press the close button instead of closing". So I solved this with the following:

subwindow->setAttribute(Qt::WA_DeleteOnClose, false);

Perhaps it's not a relevant answer but it may be useful for someone.

Upvotes: 2

azf
azf

Reputation: 2189

Yes, there is another way : you can install an event-filter on the QMdiSubWindow you create :

MdiSubWindowEventFilter * p_mdiSubWindowEventFilter;

...

QMdiSubWindow * subWindow = mdiArea->addSubWindow(pEmbeddedWidget);
subWindow->installEventFilter(p_mdiSubWindowEventFilter);
subWindow->setAttribute(Qt::WA_DeleteOnClose, true); // not mandatory, depends if you manage subWindows lifetime

with

bool MdiSubWindowEventFilter::eventFilter(QObject * obj, QEvent * e)
{
    switch (e->type())
    {
        case QEvent::Close:
        {
            QMdiSubWindow * subWindow = dynamic_cast<QMdiSubWindow*>(obj);
            Q_ASSERT (subWindow != NULL);

            //
            // do what you want here
            //

            break;
        }
        default:
            qt_noop();
    }
    return QObject::eventFilter(obj, e);
}

Upvotes: 2

Dmitry Sazonov
Dmitry Sazonov

Reputation: 8994

You can create QWidget based class like:

class CloseWatcher : public QWidget
{
  Q_OBJECT

private:
  QString m_name;

signals:
  void disposing( QString name );

public
  CloseWatcher( QWidget * p )
    : QWidget( p )
    , m_name( p->objectName() )
  {}

  ~CloseWatcher()
  {
    emit disposing( m_name );
  }
};

and just use it:

// anywhere in code
QMdiSubWindow * wnd = getSomeWnd();
CloseWatcher * watcher = new CloseWatcher( wnd );

connect( watcher, SIGNAL( disposing( QString ) ), reveiver, SLOT( onDispose( QString ) ) );

Upvotes: 0

Pherrymason
Pherrymason

Reputation: 8067

Here is what I ended coding.

#ifndef __MYSUBWINDOW_H
#define __MYSUBWINDOW_H

#include <QMdiSubWindow>
#include <QCloseEvent>
#include <QDebug>

class MyQMdiSubWindow : public QMdiSubWindow
{
    Q_OBJECT

signals:
    void closed( const QString );

protected:
    void closeEvent( QCloseEvent * closeEvent )
    {
        emit closed( this->objectName() );
        closeEvent->accept();
    }
};
#endif

Note that for my problem I need a way to identify which subwindow user is closing, and objectName does the work for me.

Upvotes: 0

Samuel Harmer
Samuel Harmer

Reputation: 4412

I don't think there is any other way than as you describe (overriding the close event) to do precisely what you're asking.

There might be other ways of achieving what you want without doing that depending on why you want to know when its closed. Other options could be the use of the destroyed signal, checking QApplication::focusWidget(), or perhaps having the parent inspect its children.

Edit in response to comment:

Signals and slots are disconnected automatically upon destruction of QObjects, and I would suggest looking at using QSharedPointers or QScopedPointers to handle your QObjects' lifespans instead. By applying these techniques, you shouldn't need a signal from a closed window.

Upvotes: 1

Related Questions