1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-21 23:55:13 -05:00

MainWindow: Add FSMs to avoid blocking on the GUI thread.

DSPDevice*Engine: Add signals to indicate when commands have been processed.
DSPDeviceSourceEngine: Fix small memory leak.
DSPEngine::removeDeviceEngineAt: Remove wait to avoid blocking thread. Return QThread to get finished signal.
DSPEngine::addDevice*Engine: Don't call deleteLater for device*Engine, as these objects are deleted manually in MainWindow, which will crash if deleteLater called first.
This commit is contained in:
srcejon 2024-10-10 13:57:11 +01:00
parent f24600b909
commit 78d0160514
12 changed files with 1271 additions and 558 deletions

View File

@ -704,6 +704,7 @@ if (BUILD_GUI)
QuickWidgets QuickWidgets
Svg Svg
SvgWidgets SvgWidgets
StateMachine
OPTIONAL_COMPONENTS OPTIONAL_COMPONENTS
WebEngineQuick WebEngineQuick
WebEngineCore WebEngineCore

View File

@ -1030,6 +1030,7 @@ bool DSPDeviceMIMOEngine::handleMessage(const Message& message)
else if (DSPAcquisitionStop::match(message)) else if (DSPAcquisitionStop::match(message))
{ {
setStateRx(gotoIdle(0)); setStateRx(gotoIdle(0));
emit acquisitionStopped();
return true; return true;
} }
else if (DSPGenerationInit::match(message)) else if (DSPGenerationInit::match(message))
@ -1053,11 +1054,13 @@ bool DSPDeviceMIMOEngine::handleMessage(const Message& message)
else if (DSPGenerationStop::match(message)) else if (DSPGenerationStop::match(message))
{ {
setStateTx(gotoIdle(1)); setStateTx(gotoIdle(1));
emit generationStopped();
return true; return true;
} }
else if (SetSampleMIMO::match(message)) { else if (SetSampleMIMO::match(message)) {
const auto& cmd = (const SetSampleMIMO&) message; const auto& cmd = (const SetSampleMIMO&) message;
handleSetMIMO(cmd.getSampleMIMO()); handleSetMIMO(cmd.getSampleMIMO());
emit sampleSet();
return true; return true;
} }
else if (AddBasebandSampleSink::match(message)) else if (AddBasebandSampleSink::match(message))
@ -1194,6 +1197,7 @@ bool DSPDeviceMIMOEngine::handleMessage(const Message& message)
BasebandSampleSink* spectrumSink = msg.getSampleSink(); BasebandSampleSink* spectrumSink = msg.getSampleSink();
spectrumSink->stop(); spectrumSink->stop();
m_spectrumSink = nullptr; m_spectrumSink = nullptr;
emit spectrumSinkRemoved();
return true; return true;
} }
else if (SetSpectrumSinkInput::match(message)) else if (SetSpectrumSinkInput::match(message))

View File

@ -356,6 +356,11 @@ private slots:
signals: signals:
void stateChanged(); void stateChanged();
void acquisitionStopped();
void sampleSet();
void generationStopped();
void spectrumSinkRemoved();
}; };
#endif // SDRBASE_DSP_DSPDEVICEMIMOENGINE_H_ #endif // SDRBASE_DSP_DSPDEVICEMIMOENGINE_H_

View File

@ -458,12 +458,14 @@ bool DSPDeviceSinkEngine::handleMessage(const Message& message)
else if (DSPGenerationStop::match(message)) else if (DSPGenerationStop::match(message))
{ {
setState(gotoIdle()); setState(gotoIdle());
emit generationStopped();
return true; return true;
} }
else if (DSPSetSink::match(message)) else if (DSPSetSink::match(message))
{ {
const auto& cmd = (const DSPSetSink&) message; const auto& cmd = (const DSPSetSink&) message;
handleSetSink(cmd.getSampleSink()); handleSetSink(cmd.getSampleSink());
emit sampleSet();
return true; return true;
} }
else if (DSPRemoveSpectrumSink::match(message)) else if (DSPRemoveSpectrumSink::match(message))
@ -476,6 +478,7 @@ bool DSPDeviceSinkEngine::handleMessage(const Message& message)
} }
m_spectrumSink = nullptr; m_spectrumSink = nullptr;
emit spectrumSinkRemoved();
return true; return true;
} }
else if (DSPAddBasebandSampleSource::match(message)) else if (DSPAddBasebandSampleSource::match(message))

View File

@ -121,6 +121,10 @@ private slots:
signals: signals:
void stateChanged(); void stateChanged();
void generationStopped();
void sampleSet();
void spectrumSinkRemoved();
}; };

View File

@ -52,7 +52,7 @@ DSPDeviceSourceEngine::DSPDeviceSourceEngine(uint uid, QObject* parent) :
DSPDeviceSourceEngine::~DSPDeviceSourceEngine() DSPDeviceSourceEngine::~DSPDeviceSourceEngine()
{ {
qDebug("DSPDeviceSourceEngine::~DSPDeviceSourceEngine"); qDebug("DSPDeviceSourceEngine::~DSPDeviceSourceEngine");
} }
void DSPDeviceSourceEngine::setState(State state) void DSPDeviceSourceEngine::setState(State state)
@ -601,12 +601,15 @@ bool DSPDeviceSourceEngine::handleMessage(const Message& message)
else if (DSPAcquisitionStop::match(message)) else if (DSPAcquisitionStop::match(message))
{ {
setState(gotoIdle()); setState(gotoIdle());
emit acquistionStopped();
return true; return true;
} }
else if (DSPSetSource::match(message)) else if (DSPSetSource::match(message))
{ {
auto cmd = (const DSPSetSource&) message; auto cmd = (const DSPSetSource&) message;
handleSetSource(cmd.getSampleSource()); handleSetSource(cmd.getSampleSource());
emit sampleSet();
return true;
} }
else if (DSPAddBasebandSampleSink::match(message)) else if (DSPAddBasebandSampleSink::match(message))
{ {
@ -620,6 +623,7 @@ bool DSPDeviceSourceEngine::handleMessage(const Message& message)
if(m_state == State::StRunning) { if(m_state == State::StRunning) {
sink->start(); sink->start();
} }
return true;
} }
else if (DSPRemoveBasebandSampleSink::match(message)) else if (DSPRemoveBasebandSampleSink::match(message))
{ {
@ -631,6 +635,8 @@ bool DSPDeviceSourceEngine::handleMessage(const Message& message)
} }
m_basebandSampleSinks.remove(sink); m_basebandSampleSinks.remove(sink);
emit sinkRemoved();
return true;
} }
return false; return false;

View File

@ -142,6 +142,10 @@ private slots:
signals: signals:
void stateChanged(); void stateChanged();
void acquistionStopped();
void sampleSet();
void sinkRemoved();
}; };
#endif // INCLUDE_DSPDEVICEENGINE_H #endif // INCLUDE_DSPDEVICEENGINE_H

View File

@ -70,12 +70,6 @@ DSPDeviceSourceEngine *DSPEngine::addDeviceSourceEngine()
m_deviceEngineReferences.push_back(DeviceEngineReference{0, m_deviceSourceEngines.back(), nullptr, nullptr, deviceThread}); m_deviceEngineReferences.push_back(DeviceEngineReference{0, m_deviceSourceEngines.back(), nullptr, nullptr, deviceThread});
deviceSourceEngine->moveToThread(deviceThread); deviceSourceEngine->moveToThread(deviceThread);
QObject::connect(
deviceThread,
&QThread::finished,
deviceSourceEngine,
&QObject::deleteLater
);
QObject::connect( QObject::connect(
deviceThread, deviceThread,
&QThread::finished, &QThread::finished,
@ -118,12 +112,6 @@ DSPDeviceSinkEngine *DSPEngine::addDeviceSinkEngine()
m_deviceEngineReferences.push_back(DeviceEngineReference{1, nullptr, m_deviceSinkEngines.back(), nullptr, deviceThread}); m_deviceEngineReferences.push_back(DeviceEngineReference{1, nullptr, m_deviceSinkEngines.back(), nullptr, deviceThread});
deviceSinkEngine->moveToThread(deviceThread); deviceSinkEngine->moveToThread(deviceThread);
QObject::connect(
deviceThread,
&QThread::finished,
deviceSinkEngine,
&QObject::deleteLater
);
QObject::connect( QObject::connect(
deviceThread, deviceThread,
&QThread::finished, &QThread::finished,
@ -166,12 +154,6 @@ DSPDeviceMIMOEngine *DSPEngine::addDeviceMIMOEngine()
m_deviceEngineReferences.push_back(DeviceEngineReference{2, nullptr, nullptr, m_deviceMIMOEngines.back(), deviceThread}); m_deviceEngineReferences.push_back(DeviceEngineReference{2, nullptr, nullptr, m_deviceMIMOEngines.back(), deviceThread});
deviceMIMOEngine->moveToThread(deviceThread); deviceMIMOEngine->moveToThread(deviceThread);
QObject::connect(
deviceThread,
&QThread::finished,
deviceMIMOEngine,
&QObject::deleteLater
);
QObject::connect( QObject::connect(
deviceThread, deviceThread,
&QThread::finished, &QThread::finished,
@ -205,38 +187,39 @@ void DSPEngine::removeLastDeviceMIMOEngine()
} }
} }
void DSPEngine::removeDeviceEngineAt(int deviceIndex) QThread * DSPEngine::removeDeviceEngineAt(int deviceIndex)
{ {
if (deviceIndex >= m_deviceEngineReferences.size()) { if (deviceIndex >= m_deviceEngineReferences.size()) {
return; return nullptr;
} }
QThread *deviceThread = nullptr;
if (m_deviceEngineReferences[deviceIndex].m_deviceEngineType == 0) // source if (m_deviceEngineReferences[deviceIndex].m_deviceEngineType == 0) // source
{ {
DSPDeviceSourceEngine *deviceEngine = m_deviceEngineReferences[deviceIndex].m_deviceSourceEngine; DSPDeviceSourceEngine *deviceEngine = m_deviceEngineReferences[deviceIndex].m_deviceSourceEngine;
QThread *deviceThread = m_deviceEngineReferences[deviceIndex].m_thread; deviceThread = m_deviceEngineReferences[deviceIndex].m_thread;
deviceThread->exit(); deviceThread->exit();
deviceThread->wait();
m_deviceSourceEngines.removeAll(deviceEngine); m_deviceSourceEngines.removeAll(deviceEngine);
} }
else if (m_deviceEngineReferences[deviceIndex].m_deviceEngineType == 1) // sink else if (m_deviceEngineReferences[deviceIndex].m_deviceEngineType == 1) // sink
{ {
DSPDeviceSinkEngine *deviceEngine = m_deviceEngineReferences[deviceIndex].m_deviceSinkEngine; DSPDeviceSinkEngine *deviceEngine = m_deviceEngineReferences[deviceIndex].m_deviceSinkEngine;
QThread *deviceThread = m_deviceEngineReferences[deviceIndex].m_thread; deviceThread = m_deviceEngineReferences[deviceIndex].m_thread;
deviceThread->exit(); deviceThread->exit();
deviceThread->wait();
m_deviceSinkEngines.removeAll(deviceEngine); m_deviceSinkEngines.removeAll(deviceEngine);
} }
else if (m_deviceEngineReferences[deviceIndex].m_deviceEngineType == 2) // MIMO else if (m_deviceEngineReferences[deviceIndex].m_deviceEngineType == 2) // MIMO
{ {
DSPDeviceMIMOEngine *deviceEngine = m_deviceEngineReferences[deviceIndex].m_deviceMIMOEngine; DSPDeviceMIMOEngine *deviceEngine = m_deviceEngineReferences[deviceIndex].m_deviceMIMOEngine;
QThread *deviceThread = m_deviceEngineReferences[deviceIndex].m_thread; deviceThread = m_deviceEngineReferences[deviceIndex].m_thread;
deviceThread->exit(); deviceThread->exit();
deviceThread->wait();
m_deviceMIMOEngines.removeAll(deviceEngine); m_deviceMIMOEngines.removeAll(deviceEngine);
} }
m_deviceEngineReferences.removeAt(deviceIndex); m_deviceEngineReferences.removeAt(deviceIndex);
return deviceThread;
} }
void DSPEngine::createFFTFactory(const QString& fftWisdomFileName) void DSPEngine::createFFTFactory(const QString& fftWisdomFileName)

View File

@ -53,7 +53,7 @@ public:
DSPDeviceMIMOEngine *addDeviceMIMOEngine(); DSPDeviceMIMOEngine *addDeviceMIMOEngine();
void removeLastDeviceMIMOEngine(); void removeLastDeviceMIMOEngine();
void removeDeviceEngineAt(int deviceIndex); QThread *removeDeviceEngineAt(int deviceIndex);
AudioDeviceManager *getAudioDeviceManager() { return &m_audioDeviceManager; } AudioDeviceManager *getAudioDeviceManager() { return &m_audioDeviceManager; }

View File

@ -343,6 +343,9 @@ target_link_libraries(sdrgui
logging logging
) )
if (Qt6_FOUND) if (Qt6_FOUND)
target_link_libraries(sdrgui
Qt6::StateMachine
)
target_link_libraries(sdrbase target_link_libraries(sdrbase
Qt::OpenGLWidgets Qt::OpenGLWidgets
) )

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,11 @@
#include <QTimer> #include <QTimer>
#include <QList> #include <QList>
#include <QProcess> #include <QProcess>
#include <QStateMachine>
#include <QState>
#include <QFinalState>
#include <QSignalTransition>
#include <QProgressDialog>
#include "settings/mainsettings.h" #include "settings/mainsettings.h"
#include "util/message.h" #include "util/message.h"
@ -43,6 +48,7 @@ class QToolButton;
class DSPEngine; class DSPEngine;
class DSPDeviceSourceEngine; class DSPDeviceSourceEngine;
class DSPDeviceSinkEngine; class DSPDeviceSinkEngine;
class DSPDeviceMIMOEngine;
class Indicator; class Indicator;
class GLSpectrumGUI; class GLSpectrumGUI;
class MainSpectrumGUI; class MainSpectrumGUI;
@ -65,13 +71,217 @@ class CommandKeyReceiver;
class ConfigurationsDialog; class ConfigurationsDialog;
class ProfileDialog; class ProfileDialog;
class SerializableInterface; class SerializableInterface;
class SDRangelSplash;
class QMenuBar; class QMenuBar;
class Workspace; class Workspace;
class MainWindow;
// Would preferablly have these FSM classes as nested classes of MainWindow
// However, as they inherit from QObject, they should have Q_OBJECT macro which isn't supported for nested classes
// Instead we have to declare them as friend classes to MainWindow
class MainWindowFSM : public QStateMachine {
Q_OBJECT
public:
MainWindowFSM(MainWindow *mainWindow, QObject *parent=nullptr);
protected:
void createStates(int states); // number of states to create, including final state
MainWindow *m_mainWindow;
QList<QState *> m_states;
QFinalState *m_finalState;
};
class AddSampleSourceFSM : public MainWindowFSM {
Q_OBJECT
public:
AddSampleSourceFSM(MainWindow *mainWindow, Workspace *deviceWorkspace, Workspace *spectrumWorkspace, int deviceIndex, bool loadDefaults, QObject *parent=nullptr);
private:
Workspace *m_deviceWorkspace;
Workspace *m_spectrumWorkspace;
int m_deviceIndex;
bool m_loadDefaults;
int m_deviceSetIndex;
DeviceAPI *m_deviceAPI;
DeviceUISet *m_deviceUISet;
DSPDeviceSourceEngine *m_dspDeviceSourceEngine;
void addEngine();
void addDevice();
void addDeviceUI();
};
class AddSampleSinkFSM : public MainWindowFSM {
Q_OBJECT
public:
AddSampleSinkFSM(MainWindow *mainWindow, Workspace *deviceWorkspace, Workspace *spectrumWorkspace, int deviceIndex, bool loadDefaults, QObject *parent=nullptr);
private:
Workspace *m_deviceWorkspace;
Workspace *m_spectrumWorkspace;
int m_deviceIndex;
bool m_loadDefaults;
int m_deviceSetIndex;
DeviceAPI *m_deviceAPI;
DeviceUISet *m_deviceUISet;
DSPDeviceSinkEngine *m_dspDeviceSinkEngine;
void addEngine();
void addDevice();
void addDeviceUI();
};
class AddSampleMIMOFSM : public MainWindowFSM {
Q_OBJECT
public:
AddSampleMIMOFSM(MainWindow *mainWindow, Workspace *deviceWorkspace, Workspace *spectrumWorkspace, int deviceIndex, bool loadDefaults, QObject *parent=nullptr);
private:
Workspace *m_deviceWorkspace;
Workspace *m_spectrumWorkspace;
int m_deviceIndex;
bool m_loadDefaults;
int m_deviceSetIndex;
DeviceAPI *m_deviceAPI;
DeviceUISet *m_deviceUISet;
DSPDeviceMIMOEngine *m_dspDeviceMIMOEngine;
void addEngine();
void addDevice();
void addDeviceUI();
};
class RemoveDeviceSetFSM : public MainWindowFSM {
Q_OBJECT
public:
RemoveDeviceSetFSM(MainWindow *mainWindow, int deviceSetIndex, QObject *parent=nullptr);
private:
int m_deviceSetIndex;
DeviceUISet *m_deviceUISet;
DSPDeviceSourceEngine *m_deviceSourceEngine;
DSPDeviceSinkEngine *m_deviceSinkEngine;
DSPDeviceMIMOEngine *m_deviceMIMOEngine;
QSignalTransition *m_t1;
QSignalTransition *m_t2;
void stopAcquisition();
void removeSink();
void removeUI();
void stopEngine();
void removeDeviceSet();
};
class RemoveAllDeviceSetsFSM : public MainWindowFSM {
Q_OBJECT
public:
RemoveAllDeviceSetsFSM(MainWindow *mainWindow, QObject *parent=nullptr);
private:
void removeNext();
};
class RemoveAllWorkspacesFSM : public MainWindowFSM {
Q_OBJECT
public:
RemoveAllWorkspacesFSM(MainWindow *mainWindow, QObject *parent=nullptr);
private:
RemoveAllDeviceSetsFSM *m_removeAllDeviceSetsFSM;
void removeDeviceSets();
void removeWorkspaces();
};
class LoadConfigurationFSM : public MainWindowFSM {
Q_OBJECT
public:
LoadConfigurationFSM(MainWindow *mainWindow, const Configuration *configuration, QProgressDialog *waitBox, QObject *parent=nullptr);
private:
const Configuration *m_configuration;
QProgressDialog *m_waitBox;
RemoveAllWorkspacesFSM *m_removeAllWorkspacesFSM;
void clearWorkspace();
void createWorkspaces();
void loadDeviceSets();
void loadDeviceSetSettings();
void loadFeatureSets();
void restoreGeometry();
};
class CloseFSM : public MainWindowFSM {
Q_OBJECT
public:
CloseFSM(MainWindow *mainWindow, QObject *parent=nullptr);
private:
void on_started();
void on_finished();
};
class InitFSM : public MainWindowFSM {
Q_OBJECT
public:
InitFSM(MainWindow *mainWindow, SDRangelSplash *splash, bool loadDefault, QObject *parent=nullptr);
private:
SDRangelSplash *m_splash;
LoadConfigurationFSM *m_loadConfigurationFSM;
void loadDefaultConfiguration();
void showDefaultConfigurations();
};
class SDRGUI_API MainWindow : public QMainWindow { class SDRGUI_API MainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
friend InitFSM;
friend AddSampleSourceFSM;
friend AddSampleSinkFSM;
friend AddSampleMIMOFSM;
friend LoadConfigurationFSM;
friend RemoveDeviceSetFSM;
friend RemoveAllDeviceSetsFSM;
friend RemoveAllWorkspacesFSM;
friend CloseFSM;
public: public:
explicit MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parser, QWidget* parent = nullptr); explicit MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parser, QWidget* parent = nullptr);
~MainWindow() final; ~MainWindow() final;
@ -130,7 +340,11 @@ private:
CommandKeyReceiver *m_commandKeyReceiver; CommandKeyReceiver *m_commandKeyReceiver;
ProfileDialog *m_profileDialog; ProfileDialog *m_profileDialog;
#if QT_CONFIG(process)
QProcess *m_fftWisdomProcess; QProcess *m_fftWisdomProcess;
#endif
bool m_settingsSaved; // Records if settings have already been saved in response to a QCloseEvent
void loadSettings(); void loadSettings();
void loadDeviceSetPresetSettings(const Preset* preset, int deviceSetIndex); void loadDeviceSetPresetSettings(const Preset* preset, int deviceSetIndex);
@ -146,6 +360,7 @@ private:
void removeDeviceSet(int deviceSetIndex); void removeDeviceSet(int deviceSetIndex);
void removeLastDeviceSet(); void removeLastDeviceSet();
void removeAllDeviceSets();
void addFeatureSet(); void addFeatureSet();
void removeFeatureSet(unsigned int featureSetIndex); void removeFeatureSet(unsigned int featureSetIndex);
void removeAllFeatureSets(); void removeAllFeatureSets();
@ -160,15 +375,30 @@ private:
int deviceIndex, int deviceIndex,
DeviceUISet *deviceUISet DeviceUISet *deviceUISet
); );
void sampleSourceCreateUI(
int deviceSetIndex,
int deviceIndex,
DeviceUISet *deviceUISet
);
void sampleSinkCreate( void sampleSinkCreate(
int deviceSetIndex, int deviceSetIndex,
int deviceIndex, int deviceIndex,
DeviceUISet *deviceUISet DeviceUISet *deviceUISet
); );
void sampleSinkCreateUI(
int deviceSetIndex,
int deviceIndex,
DeviceUISet *deviceUISet
);
void sampleMIMOCreate( void sampleMIMOCreate(
int deviceSetIndex, int deviceSetIndex,
int deviceIndex, int deviceIndex,
DeviceUISet *deviceUISet DeviceUISet *deviceUISet
);
void sampleMIMOCreateUI(
int deviceSetIndex,
int deviceIndex,
DeviceUISet *deviceUISet
); );
void deleteFeature(int featureSetIndex, int featureIndex); void deleteFeature(int featureSetIndex, int featureIndex);
void loadDefaultPreset(const QString& pluginId, SerializableInterface *serializableInterface); void loadDefaultPreset(const QString& pluginId, SerializableInterface *serializableInterface);
@ -178,6 +408,12 @@ private:
protected: protected:
void keyPressEvent(QKeyEvent* event) override; void keyPressEvent(QKeyEvent* event) override;
signals:
// For internal FSM usage
void allDeviceSetsRemoved();
void allDeviceSetsAdded();
void engineStopped();
private slots: private slots:
void handleMessages(); void handleMessages();
void handleWorkspaceVisibility(Workspace *workspace, bool visibility); void handleWorkspaceVisibility(Workspace *workspace, bool visibility);
@ -193,10 +429,13 @@ private slots:
void on_action_Graphics_triggered(); void on_action_Graphics_triggered();
void on_action_Logging_triggered(); void on_action_Logging_triggered();
void on_action_FFT_triggered(); void on_action_FFT_triggered();
#if QT_CONFIG(process)
void on_action_FFTWisdom_triggered(); void on_action_FFTWisdom_triggered();
void on_action_commands_triggered();
#endif
void on_action_My_Position_triggered(); void on_action_My_Position_triggered();
void on_action_DeviceUserArguments_triggered(); void on_action_DeviceUserArguments_triggered();
void on_action_commands_triggered(); void on_action_Welcome_triggered();
void on_action_Quick_Start_triggered() const; void on_action_Quick_Start_triggered() const;
void on_action_Main_Window_triggered() const; void on_action_Main_Window_triggered() const;
void on_action_Loaded_Plugins_triggered(); void on_action_Loaded_Plugins_triggered();
@ -228,7 +467,9 @@ private slots:
void showAllChannels(int deviceSetIndex); void showAllChannels(int deviceSetIndex);
void openDeviceSetPresetsDialog(QPoint p, const DeviceGUI *deviceGUI); void openDeviceSetPresetsDialog(QPoint p, const DeviceGUI *deviceGUI);
void commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifiers, bool release) const; void commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifiers, bool release) const;
#if QT_CONFIG(process)
void fftWisdomProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void fftWisdomProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
#endif
void orientationChanged(Qt::ScreenOrientation orientation); void orientationChanged(Qt::ScreenOrientation orientation);
}; };