PDA

View Full Version : QWidget "before destroy"-like event.



golubevsv
30th September 2014, 11:02
Hello all. In my application i have my saveSettings virtual method, that saves widget settings. This widgets using as MDI children, QDialog children and as standalone windows. What signal handler shoould I prefer to use to call my saveSettings? Destructors is not solution, because my method is virtual and call my virtual method from destructor will results undefined behaviour. loadSettings must be called AFTER child widgets are created, and loadSettings must be called BEFORE child widgets are destroyed. Here is my C++11 code:


template<class T> class ICSWidget_Template: public T {
protected:
virtual void loadSettings() = 0;
virtual void saveSettings() = 0;

virtual void showEvent(QShowEvent* pEvent) override {
T::showEvent(pEvent);

if(!m_bInitialized) {
loadSettings();
m_bInitialized = true;
}
}

// Some stuff to call saveSettings?

private:
bool m_bInitialized = false;
};


/*
This is usage of ICSWidget_Template
*/
class ICSMainWindow: public ICSWidget_Template<QMainWindow> {
// App-specific code
};

aamer4yu
30th September 2014, 12:31
May be something like when application is aboutToQuit ??
Or may be when object is destroyed.. whichever suits your need
:rolleyes::rolleyes:

golubevsv
30th September 2014, 13:03
aboutToQuit useless in my app, cause these widgets destroys at runtime, not at application termination. I can's use signal-slot connection, because MOC does not support class templates (

wysota
30th September 2014, 13:11
QObject::destroyed()

golubevsv
30th September 2014, 13:17
QObject::destroyed()

I know about this signal. How can i connect handler to this signal in template-specialized class?


UPDATE: I've traced destruction process step-by step. It consists of following steps:

1. Calling destructor of derived class
2. Calling destructor of QWidget
3. Emitting destroyed() signal

IE, in destroyed() handler VMT already destructed and I cant call my virtual method correctly.

It is correct behaviour, because destructors chaining from derived to base, until ~QObject reached. In this step destroyed() signal emitting. SO i need some signal or virtual function, that executing before QWidget-derived class destructor executed. In Windows this is WM_DESTROY message. In Qt i've found member function QWidget::destroy, but it isn't virtual, so I cannot use this

wysota
30th September 2014, 14:49
Use composition instead of inheritance to achieve virtualization.

e.g.

class SettingsHandlerBase {
public:
virtual ~SettingsHandlerBase() {}
virtual void saveSettings() = 0;
virtual void loadSettings() = 0;
};

template<class T> SettingsHandler {
public:
SettingsHandler(T *object) : m_object(object) {}
void saveSettings() { m_object->saveSettings(); }
void loadSettings() { m_object->loadSettings(); }
};

class X : public SettingsHandler<X> {
public:
X(...) : SettingsHandler<X>(this) {}
void saveSettings() { /* do your stuff */ };
void loadSettings() { /* do your stuff */ };
};

or


class SettingsSubject;
class SettingsHandler {
public:
virtual ~SettingsHandler() {}
virtual void saveSettings(SettingsSubject *) = 0;
virtual void loadSettings(SettingsSubject *) = 0;
};

class SettingsSubject {
public:
SettingsSubject(SettingsHandler *h) {
m_settingsHandler = h;
m_settingsHandler->loadSettings(this);
}
~SettingsSubject() { m_settingsHandler->saveSettings(this); delete m_settingsHandler; }
};

class Something : public SettingsSubject {
public:
Something() : SettingsSubject(new SomethingSettingsHandler) {}
};

or something in a similar fashion.