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. Doing multiple QNetworkRequest on the same QNetworkAccessManager

Doing multiple QNetworkRequest on the same QNetworkAccessManager

Scheduled Pinned Locked Moved General and Desktop
9 Posts 4 Posters 10.1k Views 1 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.
  • D Offline
    D Offline
    Dimbreath
    wrote on last edited by
    #1

    I have a QStringList with some urls to text files (Changelogs) on the internet. (Github RAWs from gist, if interesed). Each version has it's struct (Inside that struct i have QString to place the changelog).
    I have no problem requesting the changelogs, but i don't know how to assign them to their specific Version struct.

    @ struct VersionInfo {
    QString versionID;
    QString updateVersionTo;
    QString updateDate;
    QString operatingSystems;
    QString changelog;
    QString downloadLink;
    };
    @

    That's the struct of each VersionInfo. And i use this code to request:

    @ m_manager = new QNetworkAccessManager(this);

    QStringList m_urllist;
    m_urllist << "Link 1" << "Link 2";
    for(int counter = 0; counter < m_urllist.length(); counter++) {
        QNetworkRequest m_request;
        m_request.setRawHeader("User-Agent", "Autoupdater");
        m_request.setUrl(QUrl(m_urllist[counter]));
        m_manager->get(m_request);
    }@
    
    1 Reply Last reply
    0
    • M Offline
      M Offline
      Max13
      wrote on last edited by
      #2

      Hello,
      QNetworkAccessManager is an asynchronous API, which means if you want to do multiple calls, you'll have to connect them to multiple slots. Or calling 1 by 1 the requests, and connect them to the same slot where you would manage them.

      But I don't know if calling 2 times the same slot will call 2 difference slot and not the same one.

      Moreover, I noticed that you're using non-pointer QNetworkRequest, which means it will disappear and be removed from the known variables, so I think the SLOT wouldn't be called if maybe the SLOT corresponding to "counter==0" is called DURING "counter==1" for example...

      Sorry if it's not clear, if you need precision, I will ;)

      We all have started by asking questions. Then after some time, we can begin answering them.

      1 Reply Last reply
      0
      • D Offline
        D Offline
        Dimbreath
        wrote on last edited by
        #3

        [quote author="Max13" date="1356829581"]Hello,
        QNetworkAccessManager is an asynchronous API, which means if you want to do multiple calls, you'll have to connect them to multiple slots. Or calling 1 by 1 the requests, and connect them to the same slot where you would manage them.

        But I don't know if calling 2 times the same slot will call 2 difference slot and not the same one.

        Moreover, I noticed that you're using non-pointer QNetworkRequest, which means it will disappear and be removed from the known variables, so I think the SLOT wouldn't be called if maybe the SLOT corresponding to "counter==0" is called DURING "counter==1" for example...

        Sorry if it's not clear, if you need precision, I will ;)[/quote]

        Now that i think about it, i have the same question. o.O

        My problem is that i can't identify each QNetworkReply with each VersionInfo.

        1 Reply Last reply
        0
        • JKSHJ Offline
          JKSHJ Offline
          JKSH
          Moderators
          wrote on last edited by
          #4

          One solution is to create one QObject to handle each VersionInfo + QNetworkReply pair, e.g.

          @
          for(int counter = 0; counter < m_urllist.length(); counter++) {
          QNetworkRequest m_request;
          m_request.setRawHeader("User-Agent", "Autoupdater");
          m_request.setUrl(QUrl(m_urllist[counter]));
          QNetworkReply *reply = m_manager->get(m_request);

              // Store the reply, and connect the QNetworkReply::finished() signal
              // an internal slot that creates a VersionInfo based on the URL and the reply
              ChangelogProcessor *processor = new ChangelogProcessor(m_urllist[counter], reply);
          }
          

          @

          (Just be careful of memory leaks: You need to delete the ChangelogProcessor AND the QNetworkReply when you're done!)

          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

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

            @ void Updater::requestChangelogDownload()
            {
            QNetworkRequest m_request;
            m_request.setRawHeader("User-Agent", "Autoupdater");
            for(int counter = 0; counter < m_versionList.size(); counter++) {
            m_request.setUrl(QUrl(m_versionList[counter].changelog));
            m_changelogRequest.insert(m_versionList[counter].versionID, m_manager->get(m_request));
            qDebug() << "A";
            connect(m_changelogRequest.value(m_versionList[counter].versionID), SIGNAL(finished()), this, SLOT(changelogDownloaded()));
            }
            }

            void Updater::changelogDownloaded()
            {
            qDebug() << sender();
            QNetworkReply a = (QNetworkReply) sender();
            qDebug() << a->isFinished();
            qDebug() << a->readAll();
            }
            @

            I can say, not a pretty code. FOr some reason it keeps printing "A" even though m_versionList.size() is 2.
            Still it doesn't work, a->readAll() returns nothing. But i think i'm doing it poorly.

            1 Reply Last reply
            0
            • JKSHJ Offline
              JKSHJ Offline
              JKSH
              Moderators
              wrote on last edited by
              #6

              [quote author="Blastcore" date="1356846308"]
              @
              QNetworkReply a = (QNetworkReply) sender();
              @
              [/quote]

              Try a qobject_cast<> instead of a C-style cast

              Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

              1 Reply Last reply
              0
              • D Offline
                D Offline
                Dimbreath
                wrote on last edited by
                #7

                Nope, it didn't work. :/ I wonder what's going on o.O

                sender() is a QNetworkReplyImpl. Both are different.

                1 Reply Last reply
                0
                • D Offline
                  D Offline
                  Dimbreath
                  wrote on last edited by
                  #8

                  Using readyRead() signal from QNetworkReply fixed the issue.

                  1 Reply Last reply
                  0
                  • L Offline
                    L Offline
                    lgeyer
                    wrote on last edited by
                    #9

                    Be aware that readyRead() only indicates that data is available, not necessarily that the reply has finished.

                    If you want to pass information, for example a reference to the <code>VersionInfo</code> which was used to initiate the request you can use an "attribute":http://qt-project.org/doc/qt-5.0/qtnetwork/qnetworkrequest.html#setAttribute.

                    QNetworkAccessManager provides a "finished":http://qt-project.org/doc/qt-5.0/qtnetwork/qnetworkaccessmanager.html#finished signal which passes the QNetworkReply.
                    @
                    struct VersionInfo
                    {
                    ...
                    };

                    Q_DECLARE_METATYPE(VersionInfo*)

                    static const QNetworkRequest::Attribute VersionInfoAttribute = QNetworkRequest::User;

                    ...

                    connect(m_manager, &QNetworkAccessManager::finished, [](QNetworkReply reply)
                    {
                    VersionInfo
                    versionInfo = reply->request().attribute(VersionInfoAttribute)
                    .value<VersionInfo*>();
                    if (versionInfo != nullptr)
                    {
                    versionInfo->...
                    }

                    reply->deleteLater();
                    

                    });

                    ...

                    for (int counter = 0; counter < m_versionList.size(); counter++)
                    {
                    QNetworkRequest request;

                    request.setAttribute(VersionInfoAttribute,
                                         QVariant::fromValue<VersionInfo*>(&m_versionList[counter]));
                    request.setRawHeader("User-Agent", "Autoupdater");
                    request.setUrl(m_versionList[counter].changelog);
                    
                    m_manager->get(request);
                    

                    }
                    @
                    If you don't want to connect to the finished(QNetworkReply*) signal (for instance because you are reusing the QNetworkAccessManager object and don't want to receive finished signals from other requests) you can use sender() (QNetworkReplyImpl is-a QNetworkReply).

                    1 Reply Last reply
                    0

                    • Login

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