Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. General talk
  3. Brainstorm
  4. identifying signal senders
Forum Updated to NodeBB v4.3 + New Features

identifying signal senders

Scheduled Pinned Locked Moved Solved Brainstorm
17 Posts 6 Posters 3.9k Views 4 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.
  • JonBJ JonB

    @mzimmers said in identifying signal senders:

    I know that QNetworkAccessManager::get() returns a reply identifier, so I can keep a hash of these along with something to identify the sender, but...I don't know what to do with this in order to forward the reply back to the correct model.

    This is the issue? To identify which QNetworkReply belongs to which QNetworkAccessManager::get(const QNetworkRequest &request) at a later date when processing the QNetworkReply? You could subclass the QNetworkRequest to add some identifier, and retrieve that from QNetworkReply::request(). Or QNetworkReply is a QObject so you could add a QObject::setProperty() when it is returned from QNetworkAccessManager::get(). These approaches do not require maintain a hash.

    Whatever you add must be usable to identify which model the request came from. Subclassing QNetworkRequest could allow you add a QAbstractItemModel * to directly identify the data model. Or as you say you could maintain some hash/mapping if necessary.

    Finally, if for whatever reason the manager does not have any access to the models, or the request/reply is tagged with an identifier so opaque to the manager that it cannot identify the model from it but the models themselves can identify whether it pertains to them, you could have the manager emit a signal with the reply on which all the models have a slot. They could then identify whether the reply is for them. Obviously a small overhead here if they all have to listen to every reply in order to see if its for them individually.

    I don't really see the problem?

    mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by mzimmers
    #5

    @JonB said in identifying signal senders:

    This is the issue? To identify which QNetworkReply belongs to which QNetworkAccessManager::get(const QNetworkRequest &request) at a later date when processing the QNetworkReply?

    Sort of (this issue is tough to explain)...I can easily enough associate the reply with the get, but I'm not sure how to go about knowing to which model the reply should be forwarded.

    Thinking about this a little more, it's probably better to ascertain the source of the request at the point of the request, rather than after the reply comes in. I guess I could add another parameter to my signals to the manager:

    class MessageMgr : public QObject
    {
    public slots:
        void sendGet(QString message); // my current way
        void sendGet(QString message, QString model); // an alternative
    

    When a module emits a send request, it would include a string containing its name. This would be entered into a hash, with the NetworkReply * as the key, and the model name as the value.

    When the reply comes back, the message manager would look up the model in the hash, and add it to the signal that the reply came back. The signal would then go to each model, which would check for a name match before attempting to process.

    This sounds like it would work, but it's hardly elegant. A variant on this theme would be to have separate signals for each model, but that's also really a hack.

    I'm beginning to wonder if perhaps the signal/slot mechanism isn't the best way to approach this (a traditional callback method would actually work better in this case), but I'm not sure what to do.

    I'll think a little about your subclassing ideas.

    JonBJ 1 Reply Last reply
    0
    • mzimmersM mzimmers

      @JonB said in identifying signal senders:

      This is the issue? To identify which QNetworkReply belongs to which QNetworkAccessManager::get(const QNetworkRequest &request) at a later date when processing the QNetworkReply?

      Sort of (this issue is tough to explain)...I can easily enough associate the reply with the get, but I'm not sure how to go about knowing to which model the reply should be forwarded.

      Thinking about this a little more, it's probably better to ascertain the source of the request at the point of the request, rather than after the reply comes in. I guess I could add another parameter to my signals to the manager:

      class MessageMgr : public QObject
      {
      public slots:
          void sendGet(QString message); // my current way
          void sendGet(QString message, QString model); // an alternative
      

      When a module emits a send request, it would include a string containing its name. This would be entered into a hash, with the NetworkReply * as the key, and the model name as the value.

      When the reply comes back, the message manager would look up the model in the hash, and add it to the signal that the reply came back. The signal would then go to each model, which would check for a name match before attempting to process.

      This sounds like it would work, but it's hardly elegant. A variant on this theme would be to have separate signals for each model, but that's also really a hack.

      I'm beginning to wonder if perhaps the signal/slot mechanism isn't the best way to approach this (a traditional callback method would actually work better in this case), but I'm not sure what to do.

      I'll think a little about your subclassing ideas.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #6

      @mzimmers
      I don't understand your complications. If you don't want hashes and strings and lookups I said you could always just store the QAbstractItemModel *, or whatever Model *, to access the model directly. Only you know what is and is not available to you in your code.

      mzimmersM 1 Reply Last reply
      0
      • JonBJ JonB

        @mzimmers
        I don't understand your complications. If you don't want hashes and strings and lookups I said you could always just store the QAbstractItemModel *, or whatever Model *, to access the model directly. Only you know what is and is not available to you in your code.

        mzimmersM Offline
        mzimmersM Offline
        mzimmers
        wrote on last edited by
        #7

        @JonB I suppose that's an option. Of course, each model would have to have the same handler signature, but that's probably best practices anyway. I suppose I could take it a step further, and pass a pointer to the handler function instead of the entire object?

        JonBJ SGaistS 2 Replies Last reply
        0
        • mzimmersM mzimmers

          @JonB I suppose that's an option. Of course, each model would have to have the same handler signature, but that's probably best practices anyway. I suppose I could take it a step further, and pass a pointer to the handler function instead of the entire object?

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #8

          @mzimmers Of course, whatever you need to identify it when the response is received.

          1 Reply Last reply
          0
          • mzimmersM mzimmers

            @JonB I suppose that's an option. Of course, each model would have to have the same handler signature, but that's probably best practices anyway. I suppose I could take it a step further, and pass a pointer to the handler function instead of the entire object?

            SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #9

            @mzimmers hi, QNetworkReply being a QObject, you could set the signal sender as dynamic property on it. You can then retrieve it when processing the result.

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

            mzimmersM 1 Reply Last reply
            0
            • SGaistS SGaist

              @mzimmers hi, QNetworkReply being a QObject, you could set the signal sender as dynamic property on it. You can then retrieve it when processing the result.

              mzimmersM Offline
              mzimmersM Offline
              mzimmers
              wrote on last edited by
              #10

              @SGaist right, but it's the same problem -- what do I do with it? How do I go from knowing the sender to invoking a method in the sender class?

              JonBJ 1 Reply Last reply
              0
              • jeremy_kJ Offline
                jeremy_kJ Offline
                jeremy_k
                wrote on last edited by
                #11

                Return the QNetworkReply from MessageMgr::sendGet(), connect the appropriate model slot to QNetworkReply::finished(), and eliminate the intermediary handling of the reply.

                Another alternative is QNetworkRequest::setOriginatingObject() and QNetworkReply::originatingObject().

                Asking a question about code? http://eel.is/iso-c++/testcase/

                1 Reply Last reply
                1
                • mzimmersM mzimmers

                  @SGaist right, but it's the same problem -- what do I do with it? How do I go from knowing the sender to invoking a method in the sender class?

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #12

                  @mzimmers said in identifying signal senders:

                  @SGaist right, but it's the same problem -- what do I do with it? How do I go from knowing the sender to invoking a method in the sender class?

                  Again, I don't understand. I wrote earlier for this suggestion:

                  Subclassing QNetworkRequest could allow you add a QAbstractItemModel * to directly identify the data model.

                  So you would have a pointer to the model as a QAbstractItemModel *. On which you can call (QAbstractItemModel) methods directly. Or if your models share some other common interface you could derive them from YourModelBase and pass that as parameter to be able to call its methods. Or you could use qobject_cast<SpecificModelType *> to test their type and call specific model methods.

                  Or the approaches @jeremy_k mentions. Using QNetworkRequest::setOriginatingObject(someModel) saves subclassing if you don't want to do that, but it's the same approach. His direct connection of finished signal could be used if you do not actually want/need the manager to see/handle the replies.

                  One way or another you can either have the models send an identifier for themselves to the manager, which then routes replies to the model from that, or you can have the manager return the QNetworkReply * from QNetworkAccessManager::get() to the model and that puts e.g. a slot on QNetworkReply::finished() to its own code.

                  jeremy_kJ 1 Reply Last reply
                  1
                  • JonBJ JonB

                    @mzimmers said in identifying signal senders:

                    @SGaist right, but it's the same problem -- what do I do with it? How do I go from knowing the sender to invoking a method in the sender class?

                    Again, I don't understand. I wrote earlier for this suggestion:

                    Subclassing QNetworkRequest could allow you add a QAbstractItemModel * to directly identify the data model.

                    So you would have a pointer to the model as a QAbstractItemModel *. On which you can call (QAbstractItemModel) methods directly. Or if your models share some other common interface you could derive them from YourModelBase and pass that as parameter to be able to call its methods. Or you could use qobject_cast<SpecificModelType *> to test their type and call specific model methods.

                    Or the approaches @jeremy_k mentions. Using QNetworkRequest::setOriginatingObject(someModel) saves subclassing if you don't want to do that, but it's the same approach. His direct connection of finished signal could be used if you do not actually want/need the manager to see/handle the replies.

                    One way or another you can either have the models send an identifier for themselves to the manager, which then routes replies to the model from that, or you can have the manager return the QNetworkReply * from QNetworkAccessManager::get() to the model and that puts e.g. a slot on QNetworkReply::finished() to its own code.

                    jeremy_kJ Offline
                    jeremy_kJ Offline
                    jeremy_k
                    wrote on last edited by
                    #13

                    @JonB said in identifying signal senders:

                    His direct connection of finished signal could be used if you do not actually want/need the manager to see/handle the replies.

                    The struck-out portion is inaccurate. The manager can view the reply status via any of the const methods, or read content via QIODevice::peek() without interfering with later connections to the finished or readyRead signals.

                    Asking a question about code? http://eel.is/iso-c++/testcase/

                    JonBJ 1 Reply Last reply
                    0
                    • jeremy_kJ jeremy_k

                      @JonB said in identifying signal senders:

                      His direct connection of finished signal could be used if you do not actually want/need the manager to see/handle the replies.

                      The struck-out portion is inaccurate. The manager can view the reply status via any of the const methods, or read content via QIODevice::peek() without interfering with later connections to the finished or readyRead signals.

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by JonB
                      #14

                      @jeremy_k
                      Yes, but that's not what's meant. It's a question of whether the OP wants the replies routed through the manager, possibly to choose whether to send on to the models or to ignore/not do so, or whether the model receives the finished regardless and acts on it. I said "could" be used if OP does not want manager to see/handle the replies, not that it would preclude the manager seeing the responses as you wrote. As you said, not attaching the finished() signal to the model to "eliminate the intermediary handling of the reply" means that it will be attached and handled by the manager as "intermediary". Depends what the OP wants,

                      jeremy_kJ 1 Reply Last reply
                      0
                      • JonBJ JonB

                        @jeremy_k
                        Yes, but that's not what's meant. It's a question of whether the OP wants the replies routed through the manager, possibly to choose whether to send on to the models or to ignore/not do so, or whether the model receives the finished regardless and acts on it. I said "could" be used if OP does not want manager to see/handle the replies, not that it would preclude the manager seeing the responses as you wrote. As you said, not attaching the finished() signal to the model to "eliminate the intermediary handling of the reply" means that it will be attached and handled by the manager as "intermediary". Depends what the OP wants,

                        jeremy_kJ Offline
                        jeremy_kJ Offline
                        jeremy_k
                        wrote on last edited by
                        #15

                        @JonB said in identifying signal senders:

                        @jeremy_k
                        Yes, but that's not what's meant. It's a question of whether the OP wants the replies routed through the manager, possibly to choose whether to send on to the models or to ignore/not do so, or whether the model receives the finished regardless and acts on it. I said "could" be used if OP does not want manager to see/handle the replies, not that it would preclude the manager seeing the responses as you wrote. As you said, not attaching the finished() signal to the model to "eliminate the intermediary handling of the reply" means that it will be handled by the manager as "intermediary".

                        Fair enough. I had interpreted "see/handle" as non-exclusive.
                        To me, a manager that inhibits what the model sees from a successful request is acting as part of the model. HTTP and QNetworkReply has error codes to indicate lack of success.

                        Asking a question about code? http://eel.is/iso-c++/testcase/

                        1 Reply Last reply
                        0
                        • TomZT Offline
                          TomZT Offline
                          TomZ
                          wrote on last edited by TomZ
                          #16

                          Feels like the issue has little to do with the network request.

                          The issue is that the manager doesn't keep state.

                          So, if model X makes a request to the manager which is then forwarded to get an async reply. What you want to do is to ignore the fact on how its implemented and simply do what all async APIs do. Create a new QObject that emits a signal when its got a data update.

                          So what you see, as an example API, networkmanger::get() do, they return an object with a bunch of signals.

                          What you want to do is make you message-manager do the same. This means it needs to keep state. Which means it needs to route messages only back to the object it actually owns. An equivalent to the NetworkReply, maybe called SignalManagerReply...

                          The fact that the message-manager itself uses the network manager privately is a nice parallel you can probably use to mirror the workflows.

                          Edit; oh, and want to add that your initial statement of a 'model' asking he signal-manager something is breaking the model-view-controller design. You need a controller to handle an async API like the signalmanager would have (as a result of it using networkmanager).

                          Such a controller-style class is where the SignalManagerReply is used.

                          mzimmersM 1 Reply Last reply
                          0
                          • TomZT TomZ

                            Feels like the issue has little to do with the network request.

                            The issue is that the manager doesn't keep state.

                            So, if model X makes a request to the manager which is then forwarded to get an async reply. What you want to do is to ignore the fact on how its implemented and simply do what all async APIs do. Create a new QObject that emits a signal when its got a data update.

                            So what you see, as an example API, networkmanger::get() do, they return an object with a bunch of signals.

                            What you want to do is make you message-manager do the same. This means it needs to keep state. Which means it needs to route messages only back to the object it actually owns. An equivalent to the NetworkReply, maybe called SignalManagerReply...

                            The fact that the message-manager itself uses the network manager privately is a nice parallel you can probably use to mirror the workflows.

                            Edit; oh, and want to add that your initial statement of a 'model' asking he signal-manager something is breaking the model-view-controller design. You need a controller to handle an async API like the signalmanager would have (as a result of it using networkmanager).

                            Such a controller-style class is where the SignalManagerReply is used.

                            mzimmersM Offline
                            mzimmersM Offline
                            mzimmers
                            wrote on last edited by
                            #17

                            @TomZ I ended up taking Jeremy's suggestion, and it works beautifully. Keeps the message manager self contained and no need for state awareness.

                            1 Reply Last reply
                            0
                            • mzimmersM mzimmers has marked this topic as solved on

                            • Login

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