Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

same signal-slot connection in two windows



  • @JonB Thank you. I tried to connect only the Patients slot but cant see where I'm wrong..

    Patients window is opened from Settings as given below:

    void Settings::on_pushButton_patients_clicked()
    {
    
        hide();
        stagetwo = new Patients(this);
        stagetwo -> show();
    }
    

    Where stagetwo is public

    public:
         Settings(QString,QWidget *parent = nullptr);
        ~Settings();
         Patients *stagetwo;
    

    Anything wrong I'm doing here!?



  • Hi all,

    I just noticed this thing if I call both my Settings and Patients from my main the connection is successful (see below)

    #include <QApplication>
    
    tetra_grip_api api;
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        api.openSerialPort();
    
        QObject::connect(api.serial, SIGNAL(readyRead()), &api, SLOT(readData()));
        QObject::connect(api.serial, SIGNAL(error(QSerialPort::SerialPortError)),&api, SLOT(ErrorHandler(QSerialPort::SerialPortError))); // error handling
    
        Settings w(nullptr);
        w.show();
    
        Patients v(nullptr); //---------> this makes connection successfull
        v.show();
    
        return a.exec();
    }
    

    but instead, if I call Patients from Settings even though the connection is successful im not getting the expected output.

    My signal source api is a global variable which is initialized in the main as shown above.
    So constructing both classes in the main makes connection ok and I'm gettting expected output. But if I call one window from other makes connection true but my slot is not being called at all.

    What is the reason for this?



  • @russjohn834
    If you're asking me to guess, show how you gain access to tetra_grip_api api; from Settings/Patients? In these cases where do you do the connect()s from? And, how do you know your connect()s are successful?


  • Lifetime Qt Champion

    Hi,

    @russjohn834 said in same signal-slot connection in two windows:

    QObject::connect(api.serial, SIGNAL(readyRead()), &api, SLOT(readData()));
    QObject::connect(api.serial, SIGNAL(error(QSerialPort::SerialPortError)),&api, SLOT(ErrorHandler(QSerialPort::SerialPortError))); // error handling

    Since serial is internal to api why don't you connect it in the constructor of your tetra_grip_api class ?



  • @JonB

    This is how I make the connection in Settings.

    Settings::Settings(QString patientLabel, QWidget *parent) : QMainWindow(parent)
        , ui(new Ui::Settings)
    {
        ui->setupUi(this);
       
        connect(&api, &tetra_grip_api::tetraGripEvent,this, &Settings::eventHandler);
    }
    

    Connection is successfull (qDebug()<<connect(....) gives TRUE) also the a QLabel and an LED in the eventHandler slot works perfectly.

    In the same way I try to connect in the Patients:

    Patients::Patients(QWidget *parent) : QMainWindow(parent)
        , ui(new Ui::Patients)
    {
        ui->setupUi(this);
       
        connect(&api, &tetra_grip_api::tetraGripEvent,this, &Patients::eventHandlerTwo);
    }
    

    here connection is successfull (qDebug()<<connect(....) gives TRUE) but the a QLabel and an LED in the eventHandlerTwo are not working.



  • @russjohn834
    How do I know &api refers to the same, global, initialized api instance in both cases?
    And I see nothing in code about any QLabel in either case, not mentioned by you before...
    You have to supply the necessary/relevant code if you want people to help.
    Use a debugger to make sure whether slots are being hit.



  • @JonB

    I thought api should be known and accessible to all classes if intialized as global in the main.cpp

    #include <QApplication>
    
    tetra_grip_api api; //-------------> api instance
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        api.openSerialPort();
        QObject::connect(api.serial, SIGNAL(readyRead()), &api, SLOT(readData()));
        QObject::connect(api.serial, SIGNAL(error(QSerialPort::SerialPortError)),&api, SLOT(ErrorHandler(QSerialPort::SerialPortError))); // error handling
    
    
        Settings w(nullptr);
        w.show();
    
        return a.exec();
    }
    

    Correct me if I'm wrong.



  • @russjohn834
    Your Settings & Patients classes are defined in a different source module from main.cpp, right? So how do they gain access to reference the api symbol in order to compile?

     connect(&api, &tetra_grip_api::tetraGripEvent,this, &Patients::eventHandlerTwo);
    

    I am having to tease out each bit of relevant information, one at a time....



  • @JonB
    Correct. I actually did not do anything other that making apiinstance as global in main.cpp. That might be the issue. But dont know how to proceed. How do I make Patients classes know about global api instance?


  • Lifetime Qt Champion

    @russjohn834 You should avoid global variables as much as possible.
    Just pass the pointer to api to Settings & Patients constructors...



  • Did you ensure that the connection in Patients is done before the signal tetra_grip_api::tetraGripEvent is emitted? Some qDebugs around connection, in the very first line of Patients::eventHandlerTwo and in the deconstructor of Patients should help to prove that.



  • @russjohn834 said in same signal-slot connection in two windows:

    @JonB
    Correct. I actually did not do anything other that making apiinstance as global in main.cpp. That might be the issue. But dont know how to proceed. How do I make Patients classes know about global api instance?

    I truly, truly do not understand. You said your program runs but does/does not behave properly in the cases you mentioned. I asked how you can even compile your Settings/Patients modules/.cpp source files which contain the line connect(&api, ..., when api is defined in main.cpp? From what you have said/shown they should error at compile-time with a "No such variable: api" message. So I will leave others to help, who obviously understand your source code better than I.



  • @JonB Yes, that's interesting. You can't include main.cpp in Settings or in Patients. So main.cpps line

    tetra_grip_api api; //-------------> api instance
    

    isn't visible anywhere!



  • @russjohn834 If you are using QtCreator: When you go on the &api in your connect statements in both Settings and Patients and press F2 - where does it lead you to?



  • @jazzco2

    From both Settings and Patients , &api leads me here:

    #ifndef TETRA_GRIP_API_H
    #define TETRA_GRIP_API_H
    
    #include <QObject>
    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    #include <QLabel>
    #include <QMessageBox>
    #include <QTimer>
    
    #define _CRT_SECURE_NO_DEPRECATE
    
    class tetra_grip_api : public QObject
    {
        Q_OBJECT
    
    public:
        explicit tetra_grip_api(QObject *parent = nullptr);
    
        #define MAX_CONFIG_FILE_LENGTH (10000)
    
         void static send_config_file(QByteArray config, bool nonvolatile);
         void static send_long_register(uint8_t, uint32_t, uint8_t *);
         void static stimulation_set_current(unsigned int, unsigned int);
    
         QSerialPort *serial = nullptr;
    
         QTimer autoConnectionTimer;
         bool tryToAutoconnect;
    
    signals:
    
         void tetraGripEvent(STIM_GUI_TOPIC_T topic, uint8_t reg, uint32_t value);
    
    
    
    public slots:
    
         void openSerialPort();
         void closeSerialPort();
         void readData();
    
    
    private slots:
    
         void ErrorHandler(QSerialPort::SerialPortError error);
    
    private:
    
            QString comPortName;
    
    };
    
    extern tetra_grip_api api;  //----------> it leads me here
    
    #endif // TETRA_GRIP_API_H
    

  • Lifetime Qt Champion

    @russjohn834 said in same signal-slot connection in two windows:

    extern tetra_grip_api api;

    You really should not do it like this. Pass pointer to the constructors of the classes which need it.



  • @jazzco2 said in same signal-slot connection in two windows:

    @JonB Yes, that's interesting. You can't include main.cpp in Settings or in Patients.

    No, but you might be including main.h, and maybe you have extern tetra_grip_api api; there, that's the sort of thing I was trying to understand. Which finally you have shown is actually in tetra_grip_api.h, which I guess you are including into each of them?

    For the line there

    extern tetra_grip_api api;
    

    does the docs for tetra_grip_api say you are responsible for defining tetra_grip_api api; yourself like you have done in main.cpp, or does it say they (the library) are defining that global instance and you are supposed to use their instance?



  • @russjohn834 Yes, pass the pointer - and then your api can be a local variable in main. No need to define it outside as main lives as long as the application is running.



  • @jazzco2

    Could you give me an example to show how do I pass a pointer to the constructor of the classes? for ex. if I need to use it in in Settings and Patients classes ?


  • Lifetime Qt Champion

    @russjohn834 said in same signal-slot connection in two windows:

    Could you give me an example to show how do I pass a pointer to the constructor of the classes?

    Well

    tetra_grip_api api;
    Settings settings(&api);
    

    Of cource you have to change the constructor, but this is C++ basic stuff.



  • @JonB

    it did not mention anything like that. My primary requirement is to use tetra_grip_api(which is a class containing all serial communication objects) instance in every form class. That's why I made it global, but now I realize it's not a good way of programming!



  • @russjohn834 said in same signal-slot connection in two windows:
    Yes and no, it gets complicated. You may not need to pass it around that way.

    It looks like the tetra_grip_api is something in-house to you, it does not exist on the web. You have shown that tetra_grip_api.h file contains the line:

    extern tetra_grip_api api;  //----------> it leads me here
    

    You should ask the author of that file whether he intends:

    1. It is up to you to go tetra_grip_api api once in one of your own files, in order to define it, as you have done in your main.cpp; OR

    2. The tetra_grip_api library already contains this definition for you, and you are supposed to use that one.

    For now, humour me:

    Go into your main.cpp. Locate the line which reads:

    tetra_grip_api api; //-------------> api instance
    

    Now comment out that line.

    Try to rebuild & relink. What happens? Do you end up, after the linking, with an error message like: "Unresolved symbol: ''tetra_grip_api", or not?

    • If there is no error, see whether your program behaves correctly now.

    • If there is an error, unfortunately it's time we saw all your relevant code which should work but does not, because there is way too much incomplete information in what you have posted. I hesitate to say this, because I have a bad feeling that's going to be (at least) 3 .cpp files & 3 .h. files. Which is an awful lot for to paste and for us to look through :( If you could cut it down to a relevant, minimal subset which reproduces the bad behaviour you say you see, that would be really good....



  • @JonB Thanks a lot for your feedback.

    Commenting out of tetra_grip_api api in the main.cpp did end up in multiple errors with "Unresolved external symbol class tetra_grip_api api".

    From the suggestions from you guys, I feel like there is something wrong in making use of global variables. I should try also the other way of passing pointer to the class.

    But I was trying to understand a reason program behaves this way.

    As I mentioned earlier , If I call Patients behaves badly if I call it from Settings. But instead If I call both Patieints and Settings in the main (as shown below), both behave as expected. Do you immedatly think of any reason for this!?

    #include <QApplication>
    
    tetra_grip_api api;
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        api.openSerialPort();
        QObject::connect(api.serial, SIGNAL(readyRead()), &api, SLOT(readData()));
        QObject::connect(api.serial, SIGNAL(error(QSerialPort::SerialPortError)),&api, SLOT(ErrorHandler(QSerialPort::SerialPortError))); // error handling
    
    
        Settings  w(nullptr); //---->this behaves right
        Patients  v(nullptr); //---- >this behaves right
        v.show();
        w.show();
    
        return a.exec();
    }
    


  • @russjohn834
    No, because you show the case which works OK. We need to see exactly how Settings calls Patients, plus the signal connections, with whatever is relevant to that case, to judge where the problem is.



  • @JonB

    This is how I call Patients from Settings

    void Settings::on_pushButton_patients_clicked()
    {
        this->close();
        stagetwo = new Patients(this);
        stagetwo -> show();
    }
    

    where stagetwo is public

    public:
         Settings(QString,QWidget *parent = nullptr);
        ~Settings();
         Patients *stagetwo;
    

    In the Patients signal connection is as below:

    Patients::Patients( QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::Patients)
    {
        ui->setupUi(this);
    
    connect(&api, &tetra_grip_api::tetraGripEvent,this, &StageTwoPatients::eventHandlerTwo);
    
    }
    


  • @russjohn834 said in same signal-slot connection in two windows:

    void Settings::on_pushButton_patients_clicked()
    {
    this->close();
    stagetwo = new Patients(this);
    stagetwo -> show();
    }

    Just to humour me, replace by

    void Settings::on_pushButton_patients_clicked()
    {
        // this->close();
        // stagetwo = new Patients(this);
        stagetwo = new Patients(nullptr);
        stagetwo -> show();
    }
    

    Any better behaviour?



  • @JonB

    Can't see any change.



  • @russjohn834
    Very last thing: how do you know slot is not being called? Please place a breakpoint on it.



  • @JonB
    I did try with a breakpoint, and convinced that the slot is not being called when the Patients window is constructed.
    So I guess that's a serious issue using global class instance. Though I was trying to understand why this is happening ..



  • @russjohn834
    There should be no problem. I don't know what the difference is in your working vs non-working situations, I'm afraid.



  • @mrjj
    can you think of a reason why this second scenario not working?

    I have signal connection in two windows , Settings and Patients

    In Settings:

    Settings::Settings( QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::Settings)
    {
        ui->setupUi(this);
    
    connect(&api, &tetra_grip_api::tetraGripEvent,this, &Settings::eventHandler);
    ...
    }
    
    

    api is global instance of a class.

    And in Patients:

    Patients::Patients( QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::Patients)
    {
        ui->setupUi(this);
    
    connect(&api, &tetra_grip_api::tetraGripEvent,this, &Patients::eventHandlerTwo);
    
    }
    

    Situation1 - Working

    I construct both Settings and Patients window from Main

    #include <QApplication>
    
    tetra_grip_api api;
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        api.openSerialPort();
        QObject::connect(api.serial, SIGNAL(readyRead()), &api, SLOT(readData()));
        
    
        Settings  w(nullptr); //---->this behaves right
        Patients  v(nullptr); //---- >this behaves right
    
        v.show();
        w.show();
    
        return a.exec();
    }
    

    By working I mean , both the slots are being called , and QLabel set text accordingly

    Situation 2 - Not working

    I call Patients from Settings:

    void Settings::on_pushButton_patients_clicked()
    {
        this->close();
        stagetwo = new Patients(this);
        stagetwo -> show();
    }
    

    where stagetwo is public

    public:
         Settings(QString,QWidget *parent = nullptr);
        ~Settings();
         Patients *stagetwo;
    

    Here Settings works just fine (slot being called) but slot in Patients, eventhandlerTwo is not being called at all.



  • @russjohn834 Can you test what happens if you hide() the Settings instead of close() them?

    void Settings::on_pushButton_patients_clicked()
    {
        this->hide();
        stagetwo = new Patients(this);
        stagetwo -> show();
    }
    


  • @jazzco2 Did try that, in both case (hide or close) slot in the Patients not being called



  • @russjohn834
    Try commenting out in Settings::Settings

    connect(&api, &tetra_grip_api::tetraGripEvent,this, &Settings::eventHandler);
    

    Let's not have Settings connected to the signal while we sort out Patients.



  • Ok, I just wondered what happens, because close() may delete your Settings afterwards and you have no access to neither Settings nor Patients. What about the other tests:

    • Did it help to pass the pointer to Settings and to Patients in the constructor?

    • In what order are the debug messages when you add them in Settings::eventHandler() and after connecting and disconnecting (destructor) in Settings and Patients? (I wonder if the connection is cut off before it is called)



  • @jazzco2
    I suggested earlier that OP run for now with

    void Settings::on_pushButton_patients_clicked()
    {
        // this->close();
        // stagetwo = new Patients(this);
        stagetwo = new Patients(nullptr);
        stagetwo -> show();
    }
    

    Although it apparently did not solve, I suggest he revert to that code while sorting this out. It will remove some irrelevant paths of investigation.


  • Lifetime Qt Champion

    Maybe it would be easier if the OP could provide a minimal, compilable example of his problem so we can try it out by ourself. I see a good chance here that the current code is that confusing that no suggestion from here will ever help.



  • @JonB Yes that's fine. It also should be ensured that

    • both &api references point to the same instance.
      -> add debug messages at each connect(..) to display the pointer

    • the connection is alive
      -> add several debug messages as I pointed out earlier

    • the signal tetraGripEvent() is emitted in both cases
      -> keep Settings alive (using hide() instead of close()) and add a debug message in Settings::eventHandler



  • @Christian-Ehrlicher
    Please find here the minimal version of both the class files (.cpp and .h and main)

    main.cpp

    #include "settings.h"
    #include "tetra_grip_api.h"
    #include <QApplication>
    
    tetra_grip_api api;
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        api.openSerialPort();
    
        QObject::connect(api.serial, SIGNAL(readyRead()), &api, SLOT(readData()));
    
        Settings w(nullptr);
        w.show();
    
        return a.exec();
    }
    

    Settings.cpp

    #include "settings.h"
    #include "ui_settings.h"
    #include "tetra_grip_api.h"
    
     Settings ::   Settings (QWidget *parent) : QMainWindow(parent)
    QMainWindow(parent)
        , ui(new Ui::Settings )
    {
        ui->setupUi(this);
        
        connect(&api, &tetra_grip_api::tetraGripEvent,this, &Settings::eventHandler);
    
    }
    
       Settings ::~Settings ()
    {
        delete ui;
    }
    
    void Settings::on_pushButton_exit_clicked()
    {
        QApplication::quit();
        
    }
    
    void Settings::on_pushButton_patients_clicked()
    {
         this->hide();
         stagetwo = new Patients(this);
         stagetwo -> show();
    }
    
    void Settings::eventHandler(STIM_GUI_TOPIC_T topic, uint8_t reg, uint32_t value)
    {
    
        if (topic==TOPIC_STIMULATOR)
        {
            switch(reg)
            {
            case STIM_REG_BATTERY_CAPACITY_REMAINING:
    
                 ui->label_statusBat->setText("Battery remaining: "+QString::number(value)+"%");
               
                break;
            }
        }
    }
    
    

    settings.h

    #ifndef SETTINGS_H
    #define SETTINGS_H
    
    #include <QMainWindow>
    #include "patients.h"
    #include <QtSerialPort/QSerialPort>
    #include "tetra_grip_api.h"
    #include <QDebug>
    
    
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class Settings; }
    QT_END_NAMESPACE
    
    class Settings : public QMainWindow
    {
        Q_OBJECT
    
    public:
    
         Settings(QWidget *parent = nullptr);
        ~Settings();
         Patients *stagetwo;
    
    
    private slots:
    
        void on_pushButton_exit_clicked();
        void on_pushButton_patients_clicked();
    
    
    public slots:
    
     void eventHandler(STIM_GUI_TOPIC_T topic, uint8_t reg, uint32_t value);
    
    
    private:
        Ui::Settings *ui;
     
    };
    #endif
    
    

    patients.cpp (I'm giving a bit more details here because here the slot not being called from Settings)..I have a table here , user can select an entry to do something else...

    #include "patients.h"
    #include "ui_patients.h"
    #include "settings.h"
    #include <QDebug>
    #include <QFile>
    #include <QDirIterator>
    #include <QXmlStreamReader>
    #include <QMessageBox>
    #include "tetra_grip_api.h"
    
    
    Patients::Patients(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::Patients)
    {
        ui->setupUi(this);
    
    
      connect(&api, &tetra_grip_api::tetraGripEvent,this, &Patients::eventHandlerTwo);
    
     // Setup table
        ui->tableWidget->setColumnCount(5);
        ui->tableWidget->setHorizontalHeaderLabels(QStringList{"Patient ID","Name", "Surname", "LastSession", "Note"});
        ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
    
    
    
        QString path = QCoreApplication::applicationDirPath()+"/data/";
    
    
    
        QStringList qdiFilter("*.xml");
    
      //  patientData data;
    
        QDirIterator qdi( path, qdiFilter, QDir::Files);
        while (qdi.hasNext())
        {
            parseDataEntry(qdi.next());
            //data.parseDataEntry(qdi.next());
        }
    
    }
    
    void Patients::parseDataEntry(const QString dataPath)
    {
    
        QString patientID, firstName, surName, lastSession = "", pNote;
    
        // Load our XML file.
        QFile *xmlFile;
        xmlFile = new QFile(dataPath);
        if(!xmlFile->open(QIODevice::ReadOnly | QIODevice::Text))
        {
            QMessageBox::critical(this,
                                  "Error Loading Patient Data File",
                                  QString("Could not load the patient XML data file at:\r\n  %0").arg(dataPath),
                                  QMessageBox::Ok);
            return;
        }
    
        // Create an XML reader.
        QXmlStreamReader *xmlReader;
        xmlReader = new QXmlStreamReader(xmlFile);
    
    
        // Parse each element of the XML until we reach the end.
        while(!xmlReader->atEnd() && !xmlReader->hasError()) {
            // Read next element
            QXmlStreamReader::TokenType token = xmlReader->readNext();
    
            // If token is just StartDocument - go to next
            if(token == QXmlStreamReader::StartDocument) {
                continue;
            }
    
            // If token is StartElement - read it
            if(token == QXmlStreamReader::StartElement) {
    
                if(xmlReader->name() == "Name") {
                    firstName = xmlReader->readElementText();
    
                } else if(xmlReader->name() == "Surname") {
                    surName = xmlReader->readElementText();
                }
                else if(xmlReader->name() == "Patient_ID") {
                    patientID = xmlReader->readElementText();
                }
                else if(xmlReader->name() == "Date") {
                    lastSession = xmlReader->readElementText();
                }
                else if(xmlReader->name() == "Clinician_Note") {
                    pNote = xmlReader->readElementText();
                }
            }
        }
    
        if(xmlReader->hasError()) {
            QMessageBox::critical(this,
                                  "Error Parsing Patient Data File",
                                  QString("Error reading the patient file at:\r\n  %0,\r\nError:  %1").arg(dataPath,
                                                                                                           xmlReader->errorString()),
                                  QMessageBox::Ok);
            return;
        }
    
    
        // close reader and flush file
        xmlReader->clear();
        xmlFile->close();
    
    
        // Delete
        delete xmlFile;
        delete xmlReader;
    
    
        // Add a new row to the table, with the data we parsed.
        ui->tableWidget->insertRow(ui->tableWidget->rowCount());
    
        ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1,
                                 0,
                                 new QTableWidgetItem(patientID));
        ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1,
                                 1,
                                 new QTableWidgetItem(firstName));
        ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1,
                                 2,
                                 new QTableWidgetItem(surName));
        ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1,
                                 3,
                                 new QTableWidgetItem(lastSession));
        ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1,
                                 4,
                                 new QTableWidgetItem(pNote));
      //  ui->tableWidget->setCellWidget(ui->tableWidget->rowCount()-1,3, new QTableWidgetItem(lastSession))
    }
    
    Patients::~Patients()
    {
        delete ui;
    }
    
    void Patients::on_pushButton_Open_clicked()
    {
        QModelIndexList selection=ui->tableWidget->selectionModel()->selectedRows(0);
        qDebug()<<"\n The content is"<<selection[0].data().toString();
    
    ...
    }
    
    
    void Patients::eventHandlerTwo( STIM_GUI_TOPIC_T topic, uint8_t reg, uint32_t value)
    {
        ui->label_test->setText("Slot called");
     }
    
    

    and patients.h

    #ifndef PATIENTS_H
    #define PATIENTS_H
    
    #include <QMainWindow>
    #include "tetra_grip_api.h"
    
    
    namespace Ui {
    class Patients;
    }
    
    class Patients : public QMainWindow
    {
        Q_OBJECT
    
    public:
          Patients( QWidget *parent = nullptr);
        ~Patients();
        void parseDataEntry(const QString dataPath);
    
    public slots:
    
        void eventHandlerTwo(STIM_GUI_TOPIC_T topic, uint8_t reg, uint32_t value);
    
        void on_pushButton_Open_clicked();
    
    private:
        Ui::Patients *ui;
    
    };
    
    #endif 
    
    
    

    and the API class tetra_grip_api.h

    #ifndef TETRA_GRIP_API_H
    #define TETRA_GRIP_API_H
    
    #include <QObject>
    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    #include <string>
    #include <QtSerialPort/QSerialPort>
    #include <QtSerialPort/QSerialPortInfo>
    #include <QLabel>
    #include <QMessageBox>
    
    
    #define _CRT_SECURE_NO_DEPRECATE
    
    class tetra_grip_api : public QObject
    {
        Q_OBJECT
    
    public:
        explicit tetra_grip_api(QObject *parent = nullptr);
    
    
        #define MAX_CONFIG_FILE_LENGTH (10000)
    
    
         bool static send_short_block(STIM_GUI_MESSAGE_S_BLOCK_T *pblock);
         void static battery_percentage(void);
    
         QSerialPort *serial = nullptr;
    
    
    
    signals:
    
    
         void tetraGripEvent(STIM_GUI_TOPIC_T topic, uint8_t reg, uint32_t value);
    
    
    public slots:
    
         void openSerialPort();
         void closeSerialPort();
         void readData();
    
    
    private:
    
            QString comPortName;
    
    };
    
    extern tetra_grip_api api;
    
    #endif // TETRA_GRIP_API_H
    
    

    and tetra_grip_api.cpp

    #include "tetra_grip_api.h"
    #include "tetra_grip_reporter.h"
    #include <QDebug>
    #include <stdio.h>
    #include <stdlib.h>
    
    
    #define _CRT_SECURE_NO_DEPRECATE
    
    using namespace::std;
    
    tetra_grip_api::tetra_grip_api(QObject *parent) : QObject(parent)
    {
    
    
    }
    
    void tetra_grip_api::openSerialPort()
    {
        serial = new QSerialPort();
    
        QList <QSerialPortInfo>stim;
        QSerialPortInfo info;
        foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
        {
           if(info.description() == "USB Serial Port" && info.manufacturer() == "FTDI" && QString::number(info.vendorIdentifier(), 16)== "403" && QString::number(info.productIdentifier(), 16)== "6015")
            {
               comPortName = info.portName();
            }
        }
    
        serial->setPortName(comPortName);
        serial->setBaudRate(1000000); /
        serial->setDataBits(QSerialPort::Data8);
        serial->setParity(QSerialPort::NoParity);
        serial->setStopBits(QSerialPort::OneStop);
        serial->setFlowControl(QSerialPort::HardwareControl); 
        if(serial->open(QIODevice::ReadWrite))
        {
            qDebug()<<"Opend port OK";
        }
        else
        {
            qDebug()<<"Failed to open port. Error code: "<< serial->error() << serial->errorString();
        }
    
    }
    
    void tetra_grip_api::readData()
    {
    
       const QByteArray data = api.serial->readAll();
        STIM_GUI_PROTOCOL_Process_Received_Bytes((uint8_t*)data.data(), (size_t)data.length());
    
    }
    
    
    void tetra_grip_api::closeSerialPort()
    {
        if (serial->isOpen())
            serial->close();
    }
    
    
    void tetra_grip_reporter(STIM_GUI_TOPIC_T topic, uint8_t reg, uint32_t value)
    {
        emit api.tetraGripEvent(topic, reg, value);
    }
    
    
    


  • @russjohn834 said in same signal-slot connection in two windows:

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

    What is this definition doing in the middle of the Patients class?

    Meanwhile, I don't see any ~Patients() definition as per declared in the header file.


Log in to reply