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. [Solved] How can I know which slot cares about the signal I'm about to send?
Qt 6.11 is out! See what's new in the release blog

[Solved] How can I know which slot cares about the signal I'm about to send?

Scheduled Pinned Locked Moved General and Desktop
12 Posts 3 Posters 3.3k Views 2 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.
  • W Offline
    W Offline
    whereness
    wrote on last edited by whereness
    #1

    I have an application which uses a REST client to retrieve data from a web service. The REST client encapsulates the protocols used to communicate with the service, so an object that wants data from the service will connect a SLOT to the appropriate REST client's SIGNAL for that data, then it calls the method to submit the request for the data (eg. requestEmployeeList(queryParams)). The REST client sends the request to the service, and parses the reply later when it arrives, marshals the data into an appropriate data object (eg. QList<Employee>), and emits it.

    The application has multiple QTableViews attached to multiple models derived from QAbstractTableModel. These views and models need to communicate with the REST service by connecting slots to the REST client and calling its methods for requesting/posting data.

    Since the network replies are signaled asynchronously, the REST client doesn't know which object requested it, so it currently emits the appropriate signal for whatever kind of reply it receives. I'd rather have a way to communicate specifically with the object that made the request, but apart from instantiating a REST client per model and view that needs one, I'm having trouble coming up with an elegant way to do this.

    R 1 Reply Last reply
    0
    • W whereness

      I have an application which uses a REST client to retrieve data from a web service. The REST client encapsulates the protocols used to communicate with the service, so an object that wants data from the service will connect a SLOT to the appropriate REST client's SIGNAL for that data, then it calls the method to submit the request for the data (eg. requestEmployeeList(queryParams)). The REST client sends the request to the service, and parses the reply later when it arrives, marshals the data into an appropriate data object (eg. QList<Employee>), and emits it.

      The application has multiple QTableViews attached to multiple models derived from QAbstractTableModel. These views and models need to communicate with the REST service by connecting slots to the REST client and calling its methods for requesting/posting data.

      Since the network replies are signaled asynchronously, the REST client doesn't know which object requested it, so it currently emits the appropriate signal for whatever kind of reply it receives. I'd rather have a way to communicate specifically with the object that made the request, but apart from instantiating a REST client per model and view that needs one, I'm having trouble coming up with an elegant way to do this.

      R Offline
      R Offline
      raf924
      wrote on last edited by raf924
      #2

      @whereness I don't understand why you want to "communicate specifically with the object that made the request". It seems the signal/slot system you have is fine. I don't get why you want to make things more complex.

      But anyway if I understand what you want you should do something like:
      Make your request methods public slots.
      Create request/post signals in your tables
      Connect the signals to the appropriate slots
      When they want data emit those signals then catch them:

      RestClient::requestSlot(WhateverObject object){
      Table table = qobject_cast<Table>(sender());
      // Do whatever
      }
      
      W 1 Reply Last reply
      0
      • R raf924

        @whereness I don't understand why you want to "communicate specifically with the object that made the request". It seems the signal/slot system you have is fine. I don't get why you want to make things more complex.

        But anyway if I understand what you want you should do something like:
        Make your request methods public slots.
        Create request/post signals in your tables
        Connect the signals to the appropriate slots
        When they want data emit those signals then catch them:

        RestClient::requestSlot(WhateverObject object){
        Table table = qobject_cast<Table>(sender());
        // Do whatever
        }
        
        W Offline
        W Offline
        whereness
        wrote on last edited by
        #3

        @raf924 said:

        @whereness I don't understand why you want to "communicate specifically with the object that made the request". It seems the signal/slot system you have is fine. I don't get why you want to make things more complex.

        Say I have 2 employee model instances, one will query for employees at location 1, the other will query for employees at location 2. Each one will connect a slot to the REST client's employeeListReady(QList<Employee> &) signal and make their respective requests (i.e. they're unique instances of the same model class). The REST client will do its own signal/slot connections and make each request, then later when the replies signal finished(), it will parse each reply and dutifully signal with the list. Both models' slots are called for each reply. How do the models know which signal was meant for it's particular request? I can't have signals for each type of query (eg. location 1, location 2) because the UI allows user-specified queries (eg. location 1, lastname Smith). I could return the QNetworkReply pointer for each request, then the REST client would have to pass that along in it's signal to the models, then the models would have to keep track of them and check its reply object list to decide whether the signal was for them or not. But that seems messy. I'm thinking each model should have it's own REST client instance to avoid all of that, but that seems wasteful, as there will be many models and UI objects that will need to make REST requests. Seems like I'm missing something...

        R 1 Reply Last reply
        0
        • W whereness

          @raf924 said:

          @whereness I don't understand why you want to "communicate specifically with the object that made the request". It seems the signal/slot system you have is fine. I don't get why you want to make things more complex.

          Say I have 2 employee model instances, one will query for employees at location 1, the other will query for employees at location 2. Each one will connect a slot to the REST client's employeeListReady(QList<Employee> &) signal and make their respective requests (i.e. they're unique instances of the same model class). The REST client will do its own signal/slot connections and make each request, then later when the replies signal finished(), it will parse each reply and dutifully signal with the list. Both models' slots are called for each reply. How do the models know which signal was meant for it's particular request? I can't have signals for each type of query (eg. location 1, location 2) because the UI allows user-specified queries (eg. location 1, lastname Smith). I could return the QNetworkReply pointer for each request, then the REST client would have to pass that along in it's signal to the models, then the models would have to keep track of them and check its reply object list to decide whether the signal was for them or not. But that seems messy. I'm thinking each model should have it's own REST client instance to avoid all of that, but that seems wasteful, as there will be many models and UI objects that will need to make REST requests. Seems like I'm missing something...

          R Offline
          R Offline
          raf924
          wrote on last edited by
          #4

          @whereness Don't use signals on the restclient side, do as i proposed:

          @raf924 said:

          Make your request methods public slots.
          Create request/post signals in your tables
          Connect the signals to the appropriate slots
          When they want data emit those signals then catch them:

          RestClient::requestSlot(WhateverObject object){
          Table table = qobject_cast<Table>(sender());
          // Do whatever
          }
          
          W 1 Reply Last reply
          0
          • R raf924

            @whereness Don't use signals on the restclient side, do as i proposed:

            @raf924 said:

            Make your request methods public slots.
            Create request/post signals in your tables
            Connect the signals to the appropriate slots
            When they want data emit those signals then catch them:

            RestClient::requestSlot(WhateverObject object){
            Table table = qobject_cast<Table>(sender());
            // Do whatever
            }
            
            W Offline
            W Offline
            whereness
            wrote on last edited by
            #5

            @raf924 said:

            @whereness Don't use signals on the restclient side, do as i proposed:

            @raf924 said:

            Make your request methods public slots.
            Create request/post signals in your tables
            Connect the signals to the appropriate slots
            When they want data emit those signals then catch them:

            RestClient::requestSlot(WhateverObject object){
            Table table = qobject_cast<Table>(sender());
            // Do whatever
            }
            

            If I follow, you're proposing the table emit a signal when it wants data. The the restclient still needs to make the asynchronous request for data from the server, so unless I cache the table pointer on the restclient and associate it with the QNetworkReply pointer somehow, I still have the same problem. Maybe that goes with what you're suggesting? Unfortunately, there will be more than just that object type wanting to request data (eg. QTableModel derivatives), so the casting may get ugly. Maybe I'm still missing something. Thanks for your help BTW.

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

              Hi,

              One way to implement that is for the client to return an object doing the parsing of the QNetworkReply and emitting a signal when all is ready. So you can re-use your client singleton in multiple objects without the need of much intelligence in it. You can take a look at the qtenginio module for inspiration.

              Hope it helps

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

              W 1 Reply Last reply
              1
              • W whereness

                @raf924 said:

                @whereness Don't use signals on the restclient side, do as i proposed:

                @raf924 said:

                Make your request methods public slots.
                Create request/post signals in your tables
                Connect the signals to the appropriate slots
                When they want data emit those signals then catch them:

                RestClient::requestSlot(WhateverObject object){
                Table table = qobject_cast<Table>(sender());
                // Do whatever
                }
                

                If I follow, you're proposing the table emit a signal when it wants data. The the restclient still needs to make the asynchronous request for data from the server, so unless I cache the table pointer on the restclient and associate it with the QNetworkReply pointer somehow, I still have the same problem. Maybe that goes with what you're suggesting? Unfortunately, there will be more than just that object type wanting to request data (eg. QTableModel derivatives), so the casting may get ugly. Maybe I'm still missing something. Thanks for your help BTW.

                R Offline
                R Offline
                raf924
                wrote on last edited by raf924
                #7

                @whereness When i say "tables" i mean the type that will emit the signal you can test which class to cast like this:

                if (qobject_cast<TableModel>(sender()) != NULL) {
                  /* yourobjectpointer is an instance of YourQClass which should be a QObject subclass */
                }
                

                or like this

                if(sender()->metaObject()->className()=="TableModel")
                

                Or try to have only one requester type which you subclass but that will require you to alter the architecture of your program i guess.
                But yes the need to cache the table pointer goes away with my suggestion (that was the whole point of it) because it is retrieved with the sender method

                W 1 Reply Last reply
                0
                • R raf924

                  @whereness When i say "tables" i mean the type that will emit the signal you can test which class to cast like this:

                  if (qobject_cast<TableModel>(sender()) != NULL) {
                    /* yourobjectpointer is an instance of YourQClass which should be a QObject subclass */
                  }
                  

                  or like this

                  if(sender()->metaObject()->className()=="TableModel")
                  

                  Or try to have only one requester type which you subclass but that will require you to alter the architecture of your program i guess.
                  But yes the need to cache the table pointer goes away with my suggestion (that was the whole point of it) because it is retrieved with the sender method

                  W Offline
                  W Offline
                  whereness
                  wrote on last edited by
                  #8

                  @raf924 said:

                  @whereness When i say "tables" i mean the type that will emit the signal you can test which class to cast like this:

                  if (qobject_cast<TableModel>(sender()) != NULL) {
                    /* yourobjectpointer is an instance of YourQClass which should be a QObject subclass */
                  }
                  

                  or like this

                  if(sender()->metaObject()->className()=="TableModel")
                  

                  Or try to have only one requester type which you subclass but that will require you to alter the architecture of your program i guess.
                  But yes the need to cache the table pointer goes away with my suggestion (that was the whole point of it) because it is retrieved with the sender method

                  It would still have to be cached in the restclient because the response from the webserver arrives asynchronously of the request for data.

                  R 1 Reply Last reply
                  0
                  • W whereness

                    @raf924 said:

                    @whereness When i say "tables" i mean the type that will emit the signal you can test which class to cast like this:

                    if (qobject_cast<TableModel>(sender()) != NULL) {
                      /* yourobjectpointer is an instance of YourQClass which should be a QObject subclass */
                    }
                    

                    or like this

                    if(sender()->metaObject()->className()=="TableModel")
                    

                    Or try to have only one requester type which you subclass but that will require you to alter the architecture of your program i guess.
                    But yes the need to cache the table pointer goes away with my suggestion (that was the whole point of it) because it is retrieved with the sender method

                    It would still have to be cached in the restclient because the response from the webserver arrives asynchronously of the request for data.

                    R Offline
                    R Offline
                    raf924
                    wrote on last edited by
                    #9

                    @whereness Oh yeah my bad I was so focused on the part where you communicate with the objects i forgot about the actual web query. You can use this : http://doc.qt.io/qt-5/qnetworkrequest.html#setOriginatingObject
                    then get it back with this http://doc.qt.io/qt-5/qnetworkreply.html#request.

                    W 1 Reply Last reply
                    1
                    • R raf924

                      @whereness Oh yeah my bad I was so focused on the part where you communicate with the objects i forgot about the actual web query. You can use this : http://doc.qt.io/qt-5/qnetworkrequest.html#setOriginatingObject
                      then get it back with this http://doc.qt.io/qt-5/qnetworkreply.html#request.

                      W Offline
                      W Offline
                      whereness
                      wrote on last edited by
                      #10

                      @raf924 said:

                      @whereness Oh yeah my bad I was so focused on the part where you communicate with the objects i forgot about the actual web query. You can use this : http://doc.qt.io/qt-5/qnetworkrequest.html#setOriginatingObject
                      then get it back with this http://doc.qt.io/qt-5/qnetworkreply.html#request.

                      Yes! Thanks!

                      R 1 Reply Last reply
                      0
                      • W whereness

                        @raf924 said:

                        @whereness Oh yeah my bad I was so focused on the part where you communicate with the objects i forgot about the actual web query. You can use this : http://doc.qt.io/qt-5/qnetworkrequest.html#setOriginatingObject
                        then get it back with this http://doc.qt.io/qt-5/qnetworkreply.html#request.

                        Yes! Thanks!

                        R Offline
                        R Offline
                        raf924
                        wrote on last edited by
                        #11

                        @whereness You're welcome don't forget to add [SOLVED] to your topic title

                        1 Reply Last reply
                        0
                        • SGaistS SGaist

                          Hi,

                          One way to implement that is for the client to return an object doing the parsing of the QNetworkReply and emitting a signal when all is ready. So you can re-use your client singleton in multiple objects without the need of much intelligence in it. You can take a look at the qtenginio module for inspiration.

                          Hope it helps

                          W Offline
                          W Offline
                          whereness
                          wrote on last edited by
                          #12

                          @SGaist said:

                          Hi,

                          One way to implement that is for the client to return an object doing the parsing of the QNetworkReply and emitting a signal when all is ready. So you can re-use your client singleton in multiple objects without the need of much intelligence in it. You can take a look at the qtenginio module for inspiration.

                          Hope it helps

                          I ended up going this route, as how things were, this had less impact on existing code and seemed more straightforward API-wise. Thanks.

                          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