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
Forum Updated to NodeBB v4.3 + New Features

Doing multiple QNetworkRequest on the same QNetworkAccessManager

Scheduled Pinned Locked Moved General and Desktop
9 Posts 4 Posters 9.8k 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