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. Designing a "general purpose" QNetworkAccessManager interface
QtWS25 Last Chance

Designing a "general purpose" QNetworkAccessManager interface

Scheduled Pinned Locked Moved Solved General and Desktop
networkingbeginnerhelpsignals & slots
8 Posts 4 Posters 2.7k 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.
  • V Offline
    V Offline
    voiid
    wrote on last edited by
    #1

    Hello!

    As a learning exercise I am trying to create an application that displays images from a website, with the option to save individual images to disk.

    I start out with a link to an index page, containing 40-some images. Currently, I have a "Downloader" class, where I have connected the QNetworkAccessManager::finished signal to a slot that gets the QByteArray from the QNetworkReply and emits a signal. That signal is then connected to one of my "Parser" class' slots, which gets the URLs of the individual images from the QByteArray and emits another signal with the URLs in a vector (Parser is based on some code I already had, so I haven't gotten around to substituting STL-types with q-types yet).

    At this point, I would like to download each of the 40-some URLs, so that I can move on to get the direct image links from preview pages. However, because the QNetworkAccessManager::finished signal is already connected to a slot, I am kind of stuck.

    So my question is then: what is an acceptable way to structure my "Downloader" class, so that it's able to do more than just one thing?
    Having never designed a GUI application, or worked with Qt before, this whole signal-slot is still a bit foreign to me.

    I'm also looking for good up-to-date beginner resources to go along with the documentation.
    Thank you!

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

      Hi and welcome to devnet,

      Nothing forbids you to have several slots connected to a signal.

      So if I understand correctly, you would like to start the next download when the current on is finished while the received data are being parsed, correct ?

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

      V 1 Reply Last reply
      1
      • SGaistS SGaist

        Hi and welcome to devnet,

        Nothing forbids you to have several slots connected to a signal.

        So if I understand correctly, you would like to start the next download when the current on is finished while the received data are being parsed, correct ?

        V Offline
        V Offline
        voiid
        wrote on last edited by
        #3

        @SGaist Oh, I didn't know that, how does that work?

        And I'm not quite sure if I would do it while the received data is being parsed, since the result(s) of the parsing is what I would like to download next. Or are you suggesting I do something like emitting signals as the data is parsed, instead of collecting it all in a vector and sending only one signal, like I am now?

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

          Usually, pretty nicely ;) In practice it's just several connection statements, one for each target. Or depending on your needs through a QSignalMapper.

          So basically, you have a list of downloads that will generate further downloads once parsed ? In that case, nothing is wrong to parallelise the downloads. IIRC, you can have up to 6 parallel transfers with QNAM, the rest is then queued. Thus you can trigger the next download once one is finished while something else processes the data received and generates additional downloads. Some sort of download manager.

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

          V 1 Reply Last reply
          1
          • SGaistS SGaist

            Usually, pretty nicely ;) In practice it's just several connection statements, one for each target. Or depending on your needs through a QSignalMapper.

            So basically, you have a list of downloads that will generate further downloads once parsed ? In that case, nothing is wrong to parallelise the downloads. IIRC, you can have up to 6 parallel transfers with QNAM, the rest is then queued. Thus you can trigger the next download once one is finished while something else processes the data received and generates additional downloads. Some sort of download manager.

            V Offline
            V Offline
            voiid
            wrote on last edited by
            #5

            @SGaist Alright, parallelising them like that is a much better idea!

            I don't think I would be able to get away with multiple connection statements.
            My connection right now looks like this:

            connect(m_qnam, &QNetworkAccessManager::finished, this, &Downloader::indexPageDownloaded);
            

            If I were to add another connection to &QNAM::finished, surely it would not be able to decide which to use?

            The QSignalManager looks like it can connect several signals to one slot, however I have one signal I want to connect to multiple slots. It's not immediately obvious to me how I would solve this :p

            I appreciate your fast replies, by the way!

            jsulmJ 1 Reply Last reply
            0
            • V voiid

              @SGaist Alright, parallelising them like that is a much better idea!

              I don't think I would be able to get away with multiple connection statements.
              My connection right now looks like this:

              connect(m_qnam, &QNetworkAccessManager::finished, this, &Downloader::indexPageDownloaded);
              

              If I were to add another connection to &QNAM::finished, surely it would not be able to decide which to use?

              The QSignalManager looks like it can connect several signals to one slot, however I have one signal I want to connect to multiple slots. It's not immediately obvious to me how I would solve this :p

              I appreciate your fast replies, by the way!

              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on last edited by jsulm
              #6

              @voiid said in Designing a "general purpose" QNetworkAccessManager interface:

              If I were to add another connection to &QNAM::finished, surely it would not be able to decide which to use?

              There is nothing to decide: each slot connected to the signal will be called. So, if you connect two slots to that signal, both will be executed.
              You should read this: http://doc.qt.io/qt-5.7/signalsandslots.html

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              1
              • VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by
                #7

                If you want a slot to react to a specific request connect the reply directly instead of connecting the QNetworkAccessManager

                QNetworkReply* currentRep = m_qnam->get(/*your URL*/);
                connect(currentRep,&QNetworkReply::finished,[currentRep,this]()->void{indexPageDownloaded(currentRep);});
                connect(currentRep,&QNetworkReply::finished,currentRep,&QNetworkReply::deleteLater); //you probably also want this!
                

                This method lets you trigger indexPageDownloaded only for that specific reply and not for all the replies that the QNAM recieves

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                V 1 Reply Last reply
                5
                • VRoninV VRonin

                  If you want a slot to react to a specific request connect the reply directly instead of connecting the QNetworkAccessManager

                  QNetworkReply* currentRep = m_qnam->get(/*your URL*/);
                  connect(currentRep,&QNetworkReply::finished,[currentRep,this]()->void{indexPageDownloaded(currentRep);});
                  connect(currentRep,&QNetworkReply::finished,currentRep,&QNetworkReply::deleteLater); //you probably also want this!
                  

                  This method lets you trigger indexPageDownloaded only for that specific reply and not for all the replies that the QNAM recieves

                  V Offline
                  V Offline
                  voiid
                  wrote on last edited by
                  #8

                  @VRonin Excellent! This is exactly what I was looking for! Thank you!

                  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