Search code examples
c++qtqt-creatorsignals-slots

QTCreator: Signal-Slots mechanism between classes


How are you solving signals/slots mechanism between two classes, if you do not make an object from class(only inherit from class) etc? QTimer, QSerialPort, which is the source of SIGNAL, and in the second class you make connection?

Is such an approach even possible?

In my case. I have two classes usb2can_driver and canview. The usb2can_driver inherit from QSerialPort, which inherit QIODevice contained SIGNAL(readyRead()). This is used in the canview for connection with handler subroutine read_u2c()

I know, in the code is a lot of garbage from testing.

In the canview.cpp void CANview::on_connectPort_released() is made connection, and in the usb2can_driver.cpp int USB2CAN_driver::connectToPort(QString portName) is part of inherit from QSerialPort.

I will be pleasure for every answer. If you think, that question is posed incorrectly, please give me feedback.

usb2can_driver.h

#ifndef USB2CAN_DRIVER_H
#define USB2CAN_DRIVER_H

#include "QSerialPort"
#include "QTimer"
#include "QObject"
#include "QSignalSpy"


class USB2CAN_driver : public QSerialPort
{
    Q_OBJECT;

public:
    USB2CAN_driver();
    //virtual ~USB2CAN_driver();

    //QSerialPort *port_USB2CAN = new QSerialPort();


    int temporary_init_Counter = 0;
    int init();
    void USB_LoopBack();
    void Boot_Mode();
    void Config_Mode();
    void Normal_Mode();
    void LoopBack_Mode();
    QByteArray Get_Mode();

    void WriteReg(QByteArray regAdress, QByteArray value[]);
    QByteArray WriteCMD(QByteArray CMD_name, QByteArray value);
    QByteArray ReadReg(QByteArray regAdress);

    QString portName;
    int connectToPort(QString portName);
    int disconnectedFromPort();

    QTimer *tim;
    int tim_counter = 0;

public: signals:
    void readyRead();


private slots:
    QByteArray read_USB2CAN();
    void initSend();
    //void timEvent();

};

#endif // USB2CAN_DRIVER_H

usb2can_driver.cpp

#include "USB2CAN_define.h"
#include "QSerialPort"
#include "QSerialPort"
#include "QObject"
#include "QDebug"
#include <QSignalSpy>



USB2CAN_driver::USB2CAN_driver()
{
    //USB2CAN_driver:: = new QSerialPort();
    //USB2CAN_driver::Baud9600;
    //USB2CAN_driver::AllDirections;
    //qDebug() << "Open port" << USB2CAN_driver::open(QIODevice::ReadWrite);
}

/*
USB2CAN_driver::~USB2CAN_driver(){
    QObject::disconnect(USB2CAN_driver::,SIGNAL(readyRead()),USB2CAN_driver::,SLOT(QByteArray read_USB2CAN()));
}
*/

int USB2CAN_driver::connectToPort(QString portName){
    //port_USB2CAN.setPortName(portName);
    USB2CAN_driver::setPortName(portName);
    USB2CAN_driver::setBaudRate(QSerialPort::Baud9600,QSerialPort::AllDirections);
    USB2CAN_driver::setPortName(portName);
    //Reimplemented separately as signal of driver. !!!
    //qDebug() << "connect S&S in the driver, status: " << QObject::connect(this,SIGNAL(readyRead),this,SLOT(read_USB2CAN));
    //qDebug() << "connect S&S in the driver, status: " << connect(this,SIGNAL(readyRead()),this,SLOT(read_USB2CAN()));
    //QSignalSpy spy(this, SIGNAL(readyRead()));
    //qDebug() << "from driver" << spy.wait(5000) << "----" << spy.signal();
    tim = new QTimer;

    return USB2CAN_driver::open(QIODevice::ReadWrite);
}

/*
void USB2CAN_driver::timEvent(){
    qDebug() << "Tim" << tim_counter++;
    if(tim_counter >= 5){
        tim_counter = 0;
        tim->stop();
    }
}
*/

int USB2CAN_driver::disconnectedFromPort(){
    //QObject::disconnect(this,SIGNAL(readyRead()),this,SLOT(read_USB2CAN()));
    USB2CAN_driver::close();
    if(USB2CAN_driver::isOpen()){
        return 1;
    }
    else{
        qDebug() << "------------------Port is diconected-----------------";
        return 0;
    }
}


void USB2CAN_driver::USB_LoopBack(){
}
void USB2CAN_driver::Boot_Mode(){
}
void USB2CAN_driver::Config_Mode(){
}
void USB2CAN_driver::Normal_Mode(){
}
void USB2CAN_driver::LoopBack_Mode(){
}
QByteArray USB2CAN_driver::Get_Mode(){
    while(!USB2CAN_driver::waitForBytesWritten(300)){
        USB2CAN_driver::write(getMode);
    }
    return USB2CAN_driver::readAll(); //In progress...
}

void USB2CAN_driver::WriteReg(QByteArray regAdress, QByteArray value[]){
    int length = regAdress.length() + value->length();
    QByteArray len;
    len.setNum(length);
    QByteArray sendVal[] = { writeReg, len, regAdress, *value };
    QByteArray sendData;
    sendData.fromRawData(*sendVal,sizeof (sendVal));
    while(!USB2CAN_driver::waitForBytesWritten(300)){
        USB2CAN_driver::write(sendData);
    }
}
QByteArray USB2CAN_driver::WriteCMD(QByteArray CMD_name, QByteArray value){
}
QByteArray USB2CAN_driver::ReadReg(QByteArray regAdress){
}

int USB2CAN_driver::init(){
}

QByteArray USB2CAN_driver::read_USB2CAN(){
    qDebug() <<"From driver RX" << USB2CAN_driver::readAll();
    return USB2CAN_driver::readAll();
}

void USB2CAN_driver::initSend(){
}

canview.h

#define CANVIEW_H

#include <QDialog>
#include <usb2can_driver.h>

namespace Ui {
class CANview;
}

class CANview : public QDialog
{
    Q_OBJECT

public:
    explicit CANview(QWidget *parent = nullptr);
    ~CANview();

    USB2CAN_driver *u2c;
    QTimer *time;


private: signals:
    friend void USB2CAN_driver::readyRead();
private slots:
    void on_connectPort_released();

    void on_pushButton_released();

    QByteArray read_u2c();

    void timerSubrutine();

private:
    Ui::CANview *ui;
};

#endif // CANVIEW_H

canview.cpp

#include "ui_canview.h"
#include "QSignalSpy"

CANview::CANview(QWidget *parent) : QDialog(parent),ui(new Ui::CANview)
{
    ui->setupUi(this);
    u2c = new USB2CAN_driver;

}

CANview::~CANview()
{
    delete ui;   
}

//connect fcn
void CANview::on_connectPort_released()
{
    if(u2c->isOpen()){
        u2c->disconnectedFromPort();
    }
    else{
        u2c->connectToPort(ui->inputNamePort->text());
        qDebug() << "Connect rx task, status: " << connect(???,SIGNAL(readyRead()),this,SLOT(read_u2c()));
        connect(u2c->tim,SIGNAL(timeout()),this,SLOT(timerSubrutine()));
        u2c->tim->start(800);

    }

    //Controll of opened/close port
    if(u2c->isOpen()){
        ui->connectPort->setCheckState(Qt::CheckState::Checked);
    }
    else{
        ui->connectPort->setCheckState(Qt::CheckState::Unchecked);
    }
}

//Send function
void CANview::on_pushButton_released()
{
    u2c->write(ui->TX_textBrowser->toPlainText().toLatin1(),static_cast<int>(ui->TX_textBrowser->toPlainText().length()));
    qDebug() << "Send: " << static_cast<int> (ui->TX_textBrowser->toPlainText().length());
    QSignalSpy spy(u2c,SIGNAL(readyRead()));
    qDebug() << spy.signal() << spy.signalsBlocked() << spy.isValid();
}

QByteArray CANview::read_u2c(){
    qDebug() << "RX:" << u2c->readAll();
    ui->RX_textBrowser_2->setPlainText(u2c->readAll());
    return u2c->readAll();
}

void CANview::timerSubrutine(){
    qDebug() << "TimerEvent" << u2c->tim_counter++;
    if(u2c->tim_counter >= 5){
        u2c->tim->stop();
    }
}```


Solution

  • It is impossible to connect classes as mentioned by @Scheff's Cat.

    The solution is do not use inheritance from QSerialPort in the usb2can_driver. If I want connect signal of QSerialPort with slot (which is part of second class), I had to create a object from QSerialPort in the constructor of USB2CAN_driver.

    This object to allow use signal/slot mechanism.

    So in short: USB2CAN_driver:: was replaced by object port_USB2CAN For the connection in the second class (canview), i used this syntax:

    connect(u2c->port_USB2CAN,SIGNAL(readyRead()),this,SLOT(read_u2c()));
    

    Thank to Scheff's Cat, your comment was helpfully. This solution is working, but if somebody see the non-standard syntax please warning me.