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. QNetworkAccessManager finished signal emitted to late
Forum Updated to NodeBB v4.3 + New Features

QNetworkAccessManager finished signal emitted to late

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 4 Posters 2.4k Views 3 Watching
  • 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.
  • R Offline
    R Offline
    Radu.Amh
    wrote on last edited by VRonin
    #1

    I am trying to save a reply in other object which doesn't have anything to do with the downloader class but the finished signal is emitted at the end of the program so I am passing an empty string to the other object. Any ideas how to make response = m_response; work?

    #include "downloader.h"
    
    Downloader::Downloader(QObject *parent) : QObject(parent)
    {
    
    }
    
    void Downloader::doDownload(QUrl &url, QString &response)
    {
        p_manager = new QNetworkAccessManager(this);
    
        connect(p_manager, SIGNAL(finished(QNetworkReply*)),
               this, SLOT(replyFinished(QNetworkReply*)));
    
        p_manager->get(QNetworkRequest(url));
        
        response = m_response;
    }
    
    void Downloader::replyFinished (QNetworkReply *reply)
    {
        if(reply->error())
        {
            m_response = reply->errorString();
        }
        else
        {
            qDebug() << reply->header(QNetworkRequest::ContentTypeHeader).toString();
            qDebug() << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().toString();;
            qDebug() << reply->header(QNetworkRequest::ContentLengthHeader).toULongLong();
            qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
            qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
    
            m_response = reply->readAll();
        }
    
        reply->deleteLater();
    }
    
    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      @Radu.Amh said in QNetworkAccessManager finished signal emitted to late:

      response = m_response;

      What is response and m_response? You do not set either of them to any value in doDownload().

      (Z(:^

      1 Reply Last reply
      2
      • R Offline
        R Offline
        Radu.Amh
        wrote on last edited by
        #3

        in void Downloader::replyFinished (QNetworkReply *reply) you can find m_response = reply->errorString();
        response is what i want to pass to the other object

        sierdzioS 1 Reply Last reply
        0
        • mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Hi
          Why not hook up the other class to finished signal too ?
          I assume there cant be any response to copy before finished has been seen.

          Also you sentence.

          • the finished signal is emitted at the end of the program
            sounds a bit odd. does it means it takes LONG time to download or
            WHY first in the end of the program ?
          R 1 Reply Last reply
          3
          • R Radu.Amh

            in void Downloader::replyFinished (QNetworkReply *reply) you can find m_response = reply->errorString();
            response is what i want to pass to the other object

            sierdzioS Offline
            sierdzioS Offline
            sierdzio
            Moderators
            wrote on last edited by
            #5

            @Radu.Amh said in QNetworkAccessManager finished signal emitted to late:

            response is what i want to pass to the other object

            Connect that object to finished() signal, then.

            Or set the response in the replyFinished() method. Doing it in doDownload() is way too soon.

            (Z(:^

            1 Reply Last reply
            3
            • J.HilkJ Online
              J.HilkJ Online
              J.Hilk
              Moderators
              wrote on last edited by
              #6

              @Radu.Amh said in QNetworkAccessManager finished signal emitted to late:

              void Downloader::doDownload(QUrl &url, QString &response)
              {
              p_manager = new QNetworkAccessManager(this);
              connect(p_manager, SIGNAL(finished(QNetworkReply*)),
                     this, SLOT(replyFinished(QNetworkReply*)));
              
              p_manager->get(QNetworkRequest(url));
              
              response = m_response;
              }
              

              hi p_manager->get is not a synchronus function, therefore m_response in the next line will always be an empty string!

              only after the replyFinished signal is fired, is m_response not empty anymore and you can pass it along.

              also your p_manager leaks memory!


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              R 1 Reply Last reply
              5
              • mrjjM mrjj

                Hi
                Why not hook up the other class to finished signal too ?
                I assume there cant be any response to copy before finished has been seen.

                Also you sentence.

                • the finished signal is emitted at the end of the program
                  sounds a bit odd. does it means it takes LONG time to download or
                  WHY first in the end of the program ?
                R Offline
                R Offline
                Radu.Amh
                wrote on last edited by Radu.Amh
                #7

                Well, this is what I am trying to do:

                class WebPage
                {
                private:
                QUrl m_url;
                QString m_name;
                QString m_location;
                QString m_response;
                QFile p_file;

                public:
                WebPage(const QString &url, const QString &name, const QString &location);
                WebPage(const WebPage &)=delete;
                void download(Downloader &down);

                };

                void WebPage::download(Downloader &down)
                {
                down.doDownload(m_url, m_response);
                if(p_file.open(QIODevice::ReadWrite))
                {
                QTextStream stream( &p_file );
                stream << m_response;
                p_file.flush();
                p_file.close();
                }
                }

                downloading a webpage but also being able to download another webpage later in the same program.

                1 Reply Last reply
                0
                • J.HilkJ J.Hilk

                  @Radu.Amh said in QNetworkAccessManager finished signal emitted to late:

                  void Downloader::doDownload(QUrl &url, QString &response)
                  {
                  p_manager = new QNetworkAccessManager(this);
                  connect(p_manager, SIGNAL(finished(QNetworkReply*)),
                         this, SLOT(replyFinished(QNetworkReply*)));
                  
                  p_manager->get(QNetworkRequest(url));
                  
                  response = m_response;
                  }
                  

                  hi p_manager->get is not a synchronus function, therefore m_response in the next line will always be an empty string!

                  only after the replyFinished signal is fired, is m_response not empty anymore and you can pass it along.

                  also your p_manager leaks memory!

                  R Offline
                  R Offline
                  Radu.Amh
                  wrote on last edited by Radu.Amh
                  #8

                  @J.Hilk I understood get is not a synchronous function but I need the reply for the other object, webpage, so how do I make it to deliver it in time?
                  @sierdzio how do I connect the object to the finished() signal?
                  @mrjj why at the end, I've watched it with the debugger and void Downloader::replyFinished (QNetworkReply *reply) is the last function called, after that deconstructors are called

                  J.HilkJ 1 Reply Last reply
                  0
                  • R Radu.Amh

                    @J.Hilk I understood get is not a synchronous function but I need the reply for the other object, webpage, so how do I make it to deliver it in time?
                    @sierdzio how do I connect the object to the finished() signal?
                    @mrjj why at the end, I've watched it with the debugger and void Downloader::replyFinished (QNetworkReply *reply) is the last function called, after that deconstructors are called

                    J.HilkJ Online
                    J.HilkJ Online
                    J.Hilk
                    Moderators
                    wrote on last edited by
                    #9

                    @Radu.Amh
                    we would have to see a good part more of your implementation.

                    however, this quick and dirty solution should also work. But I recommend rethinking your approach:

                    void Downloader::doDownload(QUrl url, QString &response)
                    {
                        QNetworkAccessManager *manager = new QNetworkAccessManager();
                        QString str;
                        QNetworkReply *reply = manager->get(QNetworkRequest(url));
                        connect(reply, &QNetworkReply::finished, this, [reply, &str]{
                            str = reply->readAll();
                            reply->deleteLater();
                        });
                    
                    
                        QEventLoop loop;
                        connect(manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
                        loop.exec();
                    
                        manager->deleteLater();
                    
                        response = str;
                    }
                    

                    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                    Q: What's that?
                    A: It's blue light.
                    Q: What does it do?
                    A: It turns blue.

                    R 1 Reply Last reply
                    0
                    • J.HilkJ J.Hilk

                      @Radu.Amh
                      we would have to see a good part more of your implementation.

                      however, this quick and dirty solution should also work. But I recommend rethinking your approach:

                      void Downloader::doDownload(QUrl url, QString &response)
                      {
                          QNetworkAccessManager *manager = new QNetworkAccessManager();
                          QString str;
                          QNetworkReply *reply = manager->get(QNetworkRequest(url));
                          connect(reply, &QNetworkReply::finished, this, [reply, &str]{
                              str = reply->readAll();
                              reply->deleteLater();
                          });
                      
                      
                          QEventLoop loop;
                          connect(manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
                          loop.exec();
                      
                          manager->deleteLater();
                      
                          response = str;
                      }
                      
                      R Offline
                      R Offline
                      Radu.Amh
                      wrote on last edited by
                      #10

                      @J.Hilk Actually it is something I had in mind but I didn't know about QEventLoop. Thank you! Until a better solution comes this is the best.

                      J.HilkJ 1 Reply Last reply
                      0
                      • R Radu.Amh

                        @J.Hilk Actually it is something I had in mind but I didn't know about QEventLoop. Thank you! Until a better solution comes this is the best.

                        J.HilkJ Online
                        J.HilkJ Online
                        J.Hilk
                        Moderators
                        wrote on last edited by J.Hilk
                        #11

                        @Radu.Amh
                        It is a Bad solution
                        It forces synchronus behaviour on an asynchronus method

                        Better would be a Signal from your download Class that sends the recieved Data to a Slot in your other class
                        Signals can have arguments, for example a String, to send Data across


                        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                        Q: What's that?
                        A: It's blue light.
                        Q: What does it do?
                        A: It turns blue.

                        1 Reply Last reply
                        5

                        • Login

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