Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to show data from a blocking socket in QEditText
Forum Update on Monday, May 27th 2025

How to show data from a blocking socket in QEditText

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 2 Posters 374 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    DiogoM
    wrote on last edited by DiogoM
    #1

    I have a QDialog with a QEditText object and I want to show data (it's a log from a server) from a blocking socket, I get this data using an API call that uses a callback to get the lines from the this log, this callback basically never ends, only way to finish it is
    send a signal to force a close on it (in a command line I use ctrl+c).

    The issue I'm having is how to implement the thread and connect the slots/signals correctly.

    My main window has a menu option to just open the dialog where I will show the data, this dialog has the QEditText in the UI, I also have a button to "start capturing" the log.

    this is my header:

    namespace Ui {
    class EventMonitor;
    }
    
    class EventMonitor : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit EventMonitor(QWidget *parent = nullptr);
        ~EventMonitor();
    
    private slots:
        void on_pushButton_3_clicked();
    
    private:
        Ui::EventMonitor *ui;
    };
    
    class Worker : public QObject {
        Q_OBJECT
    
    public:
        Worker();
        ~Worker();
    
    public slots:
        void process();
    
    signals:
        void finished();
        void error(QString err);
    
    private:
    };
    

    In my push button event I create the thread

    void EventMonitor::on_pushButton_3_clicked()
    {
        QThread* thread = new QThread;
        Worker* worker = new Worker();
        worker->moveToThread(thread);
        connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
        connect(thread, SIGNAL(started()), worker, SLOT(process()));
        connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
        connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
        connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
        thread->start(); 
    }
    

    then In the worker process I call the API functions

    void Worker::process()
    {   
        openSession(IP, USER, PASS , &hPocket);
        DGetLogEvents(hPocket, ReceiveLogCallback, QTextEditBOX);
        emit finished();
    }
    

    This last parameter (QTextEditBox) is a void that I thought I could use to send the QTextEdit pointer and write to it inside the callback, but found out that in a different thread I couldn't write to other thread objects :(
    The callback is simple it will just write the log line to a char *szEvent .

    
    int AAP_API ReceiveLogCallback(char *szEvent, void *pParam, BOOL bFinal)
    {  
        //pParam->setText(szEvent) -> something similar to this will never work.
        emit(szEvent);
        return 0;
    }
    

    So, I was thinking that the easiest way would be emit(szEvent) to a slot that has the QTextEdit from the UI in the other thread, but I'm not sure how to do this, since the callback is not in the same class

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      Create a QString from the data your received and then use QMetaObject::invokeMethod with Qt::QueuedConnection type. That way, the slot will be executed in the right thread.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      D 1 Reply Last reply
      3
      • SGaistS SGaist

        Hi and welcome to devnet,

        Create a QString from the data your received and then use QMetaObject::invokeMethod with Qt::QueuedConnection type. That way, the slot will be executed in the right thread.

        D Offline
        D Offline
        DiogoM
        wrote on last edited by
        #3

        @SGaist

        thanks for the reply, the invoke seems like a good idea, but I'm not sure how to implement this as well.. the problem is this callback is a blocking socket that never closes, so it never leaves the callback function. How can I invoke from there if I can't access the UI object?

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Can't you pass a custom structure or data to that callback when you register it ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • D Offline
            D Offline
            DiogoM
            wrote on last edited by
            #5

            yes, I can do something like this

            void Worker::process()
            {   
                QString line;
                openSession(IP, USER, PASS , &hPocket);
                DGetLogEvents(hPocket, ReceiveLogCallback, &line);
                emit finished();
            }
            

            then in the callback

            int AAP_API ReceiveLogCallback(char *szEvent, void *pParam, BOOL bFinal)
            {
            QString *line = *pParam;
            line = QString::fromLocal8Bit(szEvent);
            return 0;
            }

            but the issue is that the function will never reach emit finished(); , it gets stuck in the callback forever.. so I need to emit this value somewhere I guess? or is it possible to connect to this QString line created in the worker class to get the value in the UI thread? Can you explain a little bit if possible? I'm somewhat noobish in QT.

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by SGaist
              #6

              Pass the pointer to your widget as parameter of the callback. Then in your callback you can use invokeMethod.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                Another possibility that will be cleaner: add a signal to your worker to emit the string and pass a pointer to your worker as parameter of your callback.

                This will keep things cleanly separated.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                D 1 Reply Last reply
                3
                • SGaistS SGaist

                  Another possibility that will be cleaner: add a signal to your worker to emit the string and pass a pointer to your worker as parameter of your callback.

                  This will keep things cleanly separated.

                  D Offline
                  D Offline
                  DiogoM
                  wrote on last edited by
                  #8

                  @SGaist said in How to show data from a blocking socket in QEditText:

                  pass a pointer t

                  thanks, I think im getting closer, but I still don't get something.

                  how do I send a signal from the callback to write on the gui now?

                  I got this so far:

                  eventmonitor.h

                  #ifndef EVENTMONITOR_H
                  #define EVENTMONITOR_H
                  
                  #include "stdafx.h"
                  #include "worker.h"
                  #include <QTextEdit>
                  #include <QThread>
                  
                  namespace Ui {
                  class EventMonitor;
                  }
                  
                  class EventMonitor : public QDialog
                  {
                      Q_OBJECT
                  
                  public:
                      explicit EventMonitor(QWidget *parent = nullptr);
                      ~EventMonitor();
                  
                  signals:
                      void sendLine(QString *line);
                  
                  private slots:
                      void on_start_logButton_clicked();    
                  
                  public slots:
                      void receive_line(QString line);
                  
                  private:
                      Ui::EventMonitor *ui;
                      Worker       m_worker;
                  };
                  
                  #endif // EVENTMONITOR_H
                  

                  eventmonitor.cpp

                  #include "eventmonitor.h"
                  #include "ui_eventmonitor.h"
                  #include "hsm.h"
                  
                  EventMonitor::EventMonitor(QWidget *parent) :
                      QDialog(parent),
                      ui(new Ui::EventMonitor)
                  {
                      ui->setupUi(this);   
                      connect(&m_worker, SIGNAL(sendLineToGui(QString)), this, SLOT(receive_line(QString)));
                      connect(this, SIGNAL(sendLine(QString *)), &m_worker, SLOT(process(QString *)));
                  }
                  
                  EventMonitor::~EventMonitor()
                  {
                      delete ui;
                  }
                  
                  void EventMonitor::receive_line(QString logLine)
                  {
                      ui->textEdit->setText(logLine);
                  }
                  
                  void EventMonitor::on_start_logButton_clicked()
                  {
                      QString line;
                      QThread* thread = new QThread;
                      Worker* worker = new Worker();
                      emit sendLine(&line);
                      worker->moveToThread(thread);
                  
                      connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
                      connect(thread, SIGNAL(started()), worker, SLOT(process()));
                      connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
                      connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
                      connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
                      thread->start();
                  }
                  

                  worker.h

                  #ifndef WORKER_H
                  #define WORKER_H
                  
                  #include <QObject>
                  #include "stdafx.h"
                  
                  class Worker : public QObject
                  {    Q_OBJECT
                  
                  public:
                       explicit Worker(QObject * parent = 0);
                      ~Worker();
                  
                  public slots:
                      void process(QString *line);
                  
                  signals:
                      void sendLineToGui(QString line);
                      void finished();
                      void error(QString err);
                  
                  private:
                  };
                  
                  #endif // WORKER_H
                  

                  worker.cpp

                  #include "worker.h"
                  
                  Worker::Worker(QObject *parent)
                  {
                  }
                  
                  Worker::~Worker()
                  {
                  }
                  
                  int AAP_API ReceiveLogCallback(char *szEvent, void *pParam, BOOL bFinal)
                  {
                      QString *line = (QString*)pParam;
                      *line = QString::fromLocal8Bit(szEvent);
                      //emit sendLineToGui
                      return 0;
                  }
                  
                  void Worker::process(QString *line)
                  {
                      HSM::HPOCKET hPocket;
                      std::string sIP(CSP::GetCSPIp());
                      HSM::libclient::openSession(CSP::GetCSPIp(), __INTERNAL_USER_CER_database__, __INTERNAL_USER_PASS_CER_database__ , &hPocket);
                      DGetLogEvents(hPocket, ReceiveLogCallback, line);
                      emit finished();
                  }
                  
                  1 Reply Last reply
                  0
                  • D Offline
                    D Offline
                    DiogoM
                    wrote on last edited by
                    #9

                    thanks! managed to do it like you said before, I passed the widget pointer to the callback parameter, it feels like bad design, but it's working.

                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      That's the wrong approach. As I suggested, use invokeMethod to emit the signal.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      1

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved