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 19 Jan 2017, 22:59 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
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 19 Jan 2017, 23:09 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 19 Jan 2017, 23:16
      1
      • S SGaist
        19 Jan 2017, 23:09

        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 19 Jan 2017, 23:16 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
        • S Offline
          S Offline
          SGaist
          Lifetime Qt Champion
          wrote on 19 Jan 2017, 23:21 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 19 Jan 2017, 23:51
          1
          • S SGaist
            19 Jan 2017, 23:21

            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 19 Jan 2017, 23:51 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!

            J 1 Reply Last reply 20 Jan 2017, 05:29
            0
            • V voiid
              19 Jan 2017, 23:51

              @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!

              J Offline
              J Offline
              jsulm
              Lifetime Qt Champion
              wrote on 20 Jan 2017, 05:29 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
              • V Offline
                V Offline
                VRonin
                wrote on 20 Jan 2017, 06:05 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 20 Jan 2017, 12:53
                5
                • V VRonin
                  20 Jan 2017, 06:05

                  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 20 Jan 2017, 12:53 last edited by
                  #8

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

                  1 Reply Last reply
                  0

                  7/8

                  20 Jan 2017, 06:05

                  • Login

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