How to pass a singleton to another class in qt - c++

In the main.cppi'm creating a singleton type of a class to use it in qml with the following function:
qmlRegisterSingletonType<DataloopWrapper>("com.xpto.connector", 1, 0, "DataloopWrapper",&DataloopWrapper::qmlInstance);
a bit down on the main.cpp i call a function of another object where i want to call a function from that singleton
maybe something like this qmlTranslator.loadLanguage(lang, DataloopWrapper::qmlInstance); is possible?
I'm declaring QmlTranslatorclass the following way:
#ifndef QMLTRANSLATOR_H
#define QMLTRANSLATOR_H
#include <QObject>
#include <QTranslator>
#include <QQmlEngine>
#include <QGuiApplication>
class QmlTranslator : public QObject
{
Q_OBJECT
public:
QmlTranslator(QQmlEngine *engine, QGuiApplication *app);
Q_INVOKABLE void selectLanguage(QString language);
void InstallTranslator();
void loadLanguage(QString language, QObject*(QQmlEngine*,QJSEngine*) objDataloop);
virtual ~QmlTranslator();
signals:
void languageChanged();
private:
QTranslator *_translator;
QQmlEngine *_engine;
QGuiApplication *_app;
};
#endif // QMLTRANSLATOR_H
I'm not finding a way to pass DataloopWrapper::qmlInstanceas argument. At least it gives error in void loadLanguage(QString language, QObject*(QQmlEngine*,QJSEngine*) objDataloop);on the qmlTranslator definition.
From a public: Members of DataloopWrapperi have the defenition of qmlInstance, it's this:
class DataloopWrapper : public QObject, public something::DataloopCBHandler,
public something::DataloopTransferCBHandler
{
Q_OBJECT
public:
explicit DataloopWrapper(QObject *parent = nullptr);
virtual ~DataloopWrapper();
static QObject *qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine);
Q_UNUSED(scriptEngine);
return new DataloopWrapper;
}

DataloopWrapper::qmlInstance is a function, that you need to call in order to get a pointer to a QObject.
For for any function you want to pass this object, you need to make it accept a pointer to a QObject (type QObject*), and don't forget to call DataloopWrapper::qmlInstance.
Translated into code:
class QmlTranslator : public QObject
{
...
void loadLanguage(QString language, QObject* objDataloop);
...
};
...
qmlTranslator.loadLanguage(lang, DataloopWrapper::qmlInstance(aQMLEngineObjectPointer, aQJSEnginePointer));

Related

to extend the lifetime of a QT object outside of the constructor

this is the problem given to me
create a project called datamanager and its base class should be QWidget
add a new class called controller inherited from QObject
and 2 slots called sensordatarecived and startdatacollection in controller
add another class called commonreader class inherited from QObject
define 2 signals called readingStarted() and readCompleted() in commonreader class
add a slot called sendData()
declare a virtual function called monitor() in the commonreader class
add 5 new sensor classes which inherit from the commonreader class
in all of the above classes reimplement the common Monitor() function
using QTimer object implement emit readingStarted() from the monitor() function of each of the 5 classes defined
implement the sendData() slot
emit signal called readcompleted inside the send dataslot()
create the object of each of the above sensor classes in the constructor of the controller
call monitor() function of the method sensor objectfrom startDataCollection()
connect readComplete() signal of each object to sensordatarecieved() of the controller.
these are the steps i have to follow for a project.i am stuck in the 14 th step and i need help.
//controller.h
class controler : public QObject
{
Q_OBJECT
public:
explicit controler(QObject *parent = nullptr);
signals:
public slots:
void sensorDataRecived();
void startDataCollection();
};
//controller.cpp
#include "controler.h"
#include <QDebug>
#include "heart_1_sensor.h"
#include "eye_2_sensor.h"
#include "brain_3_sensor.h"
#include "ear_5_sensor.h"
#include "head_4_sensor.h"
#include "commonreaderclass.h"
controler::controler(QObject *parent) : QObject(parent)
{
commonReaderClass *h1=new heart_1_Sensor;
commonReaderClass *e2=new eye_2_Sensor;
commonReaderClass *b3=new brain_3_sensor;
commonReaderClass *e5=new ear_5_sensor;
commonReaderClass *h4=new head_4_sensor;
}
void controler::sensorDataRecived()
{
qDebug()<<Q_FUNC_INFO<<endl;
}
void controler::startDataCollection()
{
}
//commonreaderclass.h
#ifndef COMMONREADERCLASS_H
#define COMMONREADERCLASS_H
#include <QObject>
class commonReaderClass : public QObject
{
Q_OBJECT
public:
explicit commonReaderClass(QObject *parent = nullptr);
virtual void monitor();
signals:
void readingStarted();
void readCompleted();
public slots:
void sendData();
};
#endif // COMMONREADERCLASS_H
//commonreaderclass.cpp
#include "commonreaderclass.h"
#include <QDebug>
#include <QTimer>
commonReaderClass::commonReaderClass(QObject *parent) : QObject(parent)
{
}
void commonReaderClass::sendData()
{
qDebug()<<"sending data has started"<<endl;
emit readCompleted();
}
//sensor1.h
#ifndef HEART_1_SENSOR_H
#define HEART_1_SENSOR_H
#include "commonreaderclass.h"
class heart_1_Sensor:public commonReaderClass
{
public:
heart_1_Sensor();
virtual void monitor();
};
#endif // HEART_1_SENSOR_H
//sensor 1.cpp
#include "heart_1_sensor.h"
#include <QDebug>
#include <QTimer>
heart_1_Sensor::heart_1_Sensor()
{
}
void heart_1_Sensor::monitor()
{
qDebug()<<"monitoring the heart"<<endl;
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(sendData()));
timer->start(2000);
emit readingStarted();
}
//and another 4 sensors of the same implementation
I agree with #molbdnilo that you should make h1, e2, ... members of the class, instead of local variables in the constructor. But in this case, there is one more consideration: the lifetime of QObject instances is special, because the parent/children relationship between them so the children can be automatically destroyed when the parent is destroyed. I recommend you this book (paper printed versions also available). Specially chapter 2 about classes and chapter 8 about QObject and other important Qt classes. This book is a curriculum, you should follow it from start to end, and also read other books.
controller.h
class Controller : public QObject
{
Q_OBJECT
public:
explicit Controller(QObject *parent = nullptr);
~Controller(); // the destructor
// ... more public members
signals:
// ...
public slots:
// ...
private:
commonReaderClass *m_h1;
commonReaderClass *m_e2;
// ...
};
I've renamed variables h1 to m_h1 and e2 to m_e2, following a common convention for member variable names, and the Controller class name starting with uppercase is another common naming convention.
controller.cpp (the classic C++ way)
Controller::Controller(QObject *parent) : QObject(parent)
{
m_h1 = new heart_1_Sensor;
m_e2 = new eye_2_Sensor;
// ...
}
Controller::~Controller()
{
delete m_h1;
delete m_e2;
// ...
}
controller.cpp (the Qt way)
Controller::Controller(QObject *parent) : QObject(parent)
{
m_h1 = new heart_1_Sensor(this);
m_e2 = new eye_2_Sensor(this);
// ...
}
Controller::~Controller()
{ }
The second version of controller.cpp is generally preferred when writing Qt based programs. You should remember that in C++ every pointer initialized with a new operation should have a corresponding delete operation. There is not automatic "garbage collection" in C++, but QObject provides a fairly comfortable mechanism to automatically delete children objects, so the destructor in this second version may be empty or you can omit entirely.

Qt: How to connect static signal from different class to slot?

So let's suppose I've got a regular Qt class MyQtClass and a class MyClass with ONLY static members. If I want to access the ui of MyQtClass I have to use Signals and Slots. So I create a static Signal (static so I can just invoke it like MyClass::mySignal();) and a slot in the Qt class. How can I connect the static signal from MyClass with the slot from the Qt class, without having an object of MyClass, since it has only got static members?
I know that classes with only static members isn't considered as a good design in c++ but I'm too far into the project by now and I want to know if there's a way to do it with only static members.
Thanks in Advance!
Code:
MyQtClass.h:
#include "ui_MyQtClass.h"
class MyQtClass : public QMainWindow
{
Q_OBJECT
public:
MyQtClass(QWidget *parent = Q_NULLPTR);
Q_SLOT void mySlot();
private:
Ui::MyQtClassClass ui;
};
MyClass.h:
#pragma once
#include <QtWidgets/QMainWindow>
class MyClass : public QObject
{
public:
static void myFunction1();
static void myFunction2();
/*--- More Stuff ---*/
Q_SIGNAL static void mySignal();
};
As indicated in this thread it is not possible to emit static signals since it is always associated with a QObject, as an alternative they create a singleton that would be equivalent to what you want.
#include <QtCore>
class Receiver: public QObject
{
Q_OBJECT
public:
using QObject::QObject;
Q_SLOT void mySlot(){
qDebug()<< __PRETTY_FUNCTION__;
QCoreApplication::quit();
}
};
class Sender: public QObject
{
Q_OBJECT
using QObject::QObject;
public:
static Sender& instance(){
static Sender m_instance;
return m_instance;
}
static void myFunction1(){
emit instance().mySignal();
}
Q_SIGNAL void mySignal();
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Receiver r;
QObject::connect(&Sender::instance(), &Sender::mySignal, &r, &Receiver::mySlot);
QTimer::singleShot(1000, &Sender::myFunction1);
return a.exec();
}
#include "main.moc"

Using signals into a class which is inheriting from QObject

I'm asking if there is a way to use signals in a class which inherits from QObject like this:
mysuperclass.cpp
#include "mysuperclass.h"
MySuperclass::MySuperclass(quint16 port, QObject *parent) :
QObject(parent), port(port)
{
this->connected = false;
}
mysuperclass.h
#include <QAbstractSocket>
class MySuperclass: public QObject
{
Q_OBJECT
public:
explicit MySuperclass(quint16 port = 0, QObject *parent = 0);
signals:
//there is nothing here
public slots:
virtual void newValue(){qDebug() << "newValue";}
virtual void connectionEstablished(){qDebug() << "connectionEstablished";}
virtual void disconnected(){qDebug() << "disconnected";}
protected:
QAbstractSocket* networkSocket;
quint16 port;
bool connected;
};
mysubclass.cpp
#include <QTcpSocket>
#include <QHostAddress>
MySubClass::MySubClass(quint16 ServerPort, QObject *parent) :
MySuperClass(ServerPort, parent)
{
this->networkSocket = new QTcpSocket(this);
...
connect(this->networkSocket, SIGNAL(connected()),this,
SLOT(connectionEstablished()));
connect(this->networkSocket, SIGNAL(disconnected()),this,
SLOT(disconnected()));
connect(this->networkSocket, SIGNAL(readyRead()),this, SLOT(newValue()));
}
mysubclass.h
#include <QObject>
#include "mysuperclass.h"
class MySubClass: public MySuperClass
{
public:
MySubClass(quint16 ServerPort, QObject* parent=0);
public slots:
void newValue();
void connectionEstablished();
void disconnected();
};
You must include the Q_OBJECT macro in the derived class too (but don't derive from QObject again). The macro is only mandatory if the derived class declares signals or slots. For emitting parent's signals or connecting with parent's slots it is not necessary (it also means that it is not necessary to re-define already existing signals or slots).
From Qt's documentation:
The Q_OBJECT macro must appear in the private section of a class definition that declares its own signals and slots or that uses other services provided by Qt's meta-object system.
Example
class MySubClass : public MySuperClass {
Q_OBJECT
public:
MySubClass(quint16 ServerPort, QObject* parent=0);
public slots:
void newValue();
void connectionEstablished();
void disconnected();
};
On the other hand, if you want to connect to a slot in the parent class but implement it in a derived one, then you must make it virtual:
class MySuperclass : public QObject {
Q_OBJECT
// ...
public slots:
virtual void newValue(); // can be virtual pure also
};
class MySubClass : public MySuperClass {
public:
virtual void newValue() override; // overrides parent's
}
Note that there is no need to use the Q_OBJECT macro nor to use the slot: label in the derived class. Slots are normal methods after all. Of course, you have to use it if you add new slots or signals.

QObject signals and slots not accessing function

I have a function which I am trying to connect via signals and slots but the function isn't being called when I run the executable file. I have put a debug error in my function so I know it isn't being called. My code is shown below:
My header file:
#include "MyWidget.h"
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass: public QObject{
Q_OBJECT
public:
MyClass( QObject *parent = nullptr);
MyWidget *myWidget;
public slots:
void setTranslation(int value);
};
#endif
My source file:
#include "MyClass.h"
MyClass::MyClass(QObject *parent): QObject(parent)
{
some code here....
QSlider *xSlider = new QSlider(Qt::Vertical);
xSlider->setRange(0, 10);
QObject::connect(xSlider, SIGNAL(valueChanged(int)),
this, SLOT(setTranslation(int)));
some code here...
}
void MyClass::setTranslation(int value)
{
some code here...
}
You forgot to add the Q_OBJECT macro immediately after the class declaration. It is what the MOC (Meta Object Compiler) uses to generate additional meta information for your code.
class MyClass: public QObject
{
Q_OBJECT
// all other class data, member function declaration
public:
MyClass( QObject *parent = nullptr );
};
This should be good enough.
EDIT:
Also remember to take a nullptr defaulted QObject pointer in your default constructor.

Access UI elements from another class c++

I have a problem with accessing ui elements from another class(with instance). I have a second QMainWindow in my application, I can access in secondWindow.cxx class all ui elements but not in read.cxx class. My code looks like following. Where is my mistake? Thank you for your help.
-------------------------------secondWindow.h------------------------------------
#ifndef __secondWindow_h
#define __secondWindow_h
#include "ui_secondwindow.h"
class secondWindow : public QMainWindow
{
friend class read;
igstkStandardClassBasicTraitsMacro(secondWindow, QMainWindow);
Q_OBJECT
public:
igstkStateMachineMacro();
secondWindow();
virtual ~secondWindow();
void createSignalAndSlots();
public slots:
void secondWindowTest();
protected:
private:
Ui::secondMainWindow m_secondWindowUI;
};
#endif
-------------------------------secondWindow.cxx------------------------------------
#include "secondWindow.moc"
#include "secondWindow.h"
#include "read.h"
secondWindow::secondWindow() :m_StateMachine(this)
{
m_secondWindowUI.setupUi(this);
createSignalAndSlots();
}
void secondWindow::createSignalAndSlots()
{
connect(m_secondWindowUI.pushButton1, SIGNAL(clicked()),this, SLOT(secondWindowTest()));
connect(m_secondWindowUI.pushButton2, SIGNAL(clicked()), read::instance(), SLOT(readTest()));
}
void secondWindow::secondWindowTest()
{
m_secondWindowUI.pushButton1->setEnabled(true); //OK
}
secondWindow::~secondWindow(){}
---------------------------------read.h--------------------------------------
#pragma once
#include "secondWindow.h"
class read : public QObject
{
Q_OBJECT
public:
static read *instance();
read();
virtual ~read() {}
public slots:
void readTest();
protected:
secondWindow *m_readUI;
static read *m_read;
private:
};
---------------------------------read.cxx--------------------------------------
#include <read.moc>
#include "secondWindow.h"
#include "read.h"
read *read::m_read= NULL;
read::read()
{
m_readUI = dynamic_cast<secondWindow*>( QApplication::instance() );
}
read *read::instance()
{
if(m_read == NULL)
m_read = new read();
return m_read;
}
void read::readTest()
{
m_readUI->m_secondWindowUI.qlabelTest->setText("test"); //segmentation fault
}
You are casting a QApplication::instance(), which is a QApplication * deriving from QCoreApplication * deriving from QObject *. That won't work, it's not a secondWindow *, not even a QMainWindow *, not even a QWidget *.
Apart from that, your coding style is rather strange -- in Qt, it's customary to use CamelCase for classes, not thisStuff which usually applies to functions and methods. Including <read.moc> is just wrong. Why is read::m_read static? Finally, the coupling between the two window classes is set up in a strange way (accessing global stuff like QApplication just to get a reference to another window smells ugly code). A much better and more obvious approach is to either wrap all of your windows in a parent object or setting up the dependencies explicitly, perhaps like this:
MainWindow *mainWindow = new MainWindow();
SecondWindow *second = new SecondWindow(mainWindow);
UtilityWindow *utilityWin = new UtilityWindow(second);