Connecting to a signal in a contained instance



  • Hello everybody,
    I can't find a more elegant way of connecting to a signal which is emitted by a class encapsulated inside another class that I am using, Here is the sample code:

    class Worker : public QObject
    {
        Q_OBJECT
    public:
    	explicit Worker() : m_timer(this) {}
    	virtual ~Worker();
    
    private slots:
    	void init()
    	{
    		connect(&m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
    		m_timer.start(100);
    	}
        void onTimeout()
    	{
    		double v = 0;
    		//if (condition)
    		emit newValue(v);
    	}
    	void finish()
    	{
    		m_timer.stop();
    		emit finished();
    	}
    
    private:
    	QTimer m_timer;
    signals:
    	void newValue(double v); //the "hidden" signal
    	void finished();
    
    };
    
    class ThreadContainer : public ThreadContainer
    {
        Q_OBJECT
    public:
    	explicit ThreadContainer(QObject* parent = NULL)
    	{
    		worker = new Worker;
    		t = new QThread(this);
    		worker->moveToThread(t);
    		connect(t, SIGNAL(started()), worker, SLOT(init()));
    		connect(this, SIGNAL(sig_finish()), worker, SLOT(finish()));
    		connect(worker, SIGNAL(finished()), t, SLOT(quit()));
    		connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    		connect(t, SIGNAL(finished()), t, SLOT(deleteLater()));
    		t->start();
    	};
    	virtual ~ThreadContainer()
    	{
    		emit sig_finish();
    		t->quit();
    		t->wait(1000);
    	};
    	const Worker* getWorker() {return const_cast<Worker*>(worker);};
    
    signals:
    	void newValue(double v);
    	void sig_finish();
       
    public slots:
    	void slotNewValue(double v);
    
    private:
        QThread* t;
        Worker* worker;
    };
    
    
    class window : public QMainWindow
    {
    	Q_OBJECT
    
    public:
    	window(QWidget *parent = 0)
    	{
    		ui.setupUi(this);
    		connect(m_Container.getWorker(), SIGNAL(newValue(double)), this, SLOT(slotNewValue(double)));
    	}
    	~window(){};
    
    
    private slots:
    	void slotNewValue(double v)
    	{
    		//display the new value
    		ui.lbl->setText(QString("%1").arg(v));
    	}
    private:
    	Ui::QtTestClass ui;
    	ThreadContainer m_Container;
    
    protected:
    };
    

    I would like to avoid calling "m_Container.getWorker()" to get the pointer to the instance emitting the signal.
    Another way would be relaying the signal from the Worker class to ThreadContainer and then to my window class, but that's probably not efficient, either.
    Any suggestions?



  • Hi and welcome to devnet,

    connecting a signal to another signal is supported and also a good practice when you want to hide the internal implementation of a composed object.

    In you case you can connect the Worker::newValue() signal to the ThreadContainer::newValue() signal and the handle the ThreadContainer::newValue() signal in your MainWindow



  • Thanks for the quick reply. I was concerned about speed, as the timer in the worker is used for polling a device every 10ms, so, theoretically a signal could be triggered every time. Do you think it would not be relevant?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.