Multiple Slot to same QNetworkAccessManager



  • Hello guys, i'm new on QT and had some problems with slots.

    Then, I need send two post

    1. I connect to webserver to check if username is correct.
    2. If username is correct I send one file to server.
    void ClassOne::checkUser{
    connect(networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinishValid(QNetworkReply*)));
    networkMgr->post(request, datatoSend);
    
    void classOne:onFinishValid(QNetworkReply *reply){
    	QString data = (QString) reply->readAll();
    	...
            if(true){
                 ...some code
             showMessage("Login OK! Sending file!")
             sendFile();
           } else{
               showMessage("Login fail")
            } 
             reply->deleteLater();
    }
    
    //Class 2
    ClassTwo::sendFile(){
                 connect(mpNetworkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinish(QNetworkReply*)));  //Other slot
                 networkMgr->post(request, datatoSend);
    }
    
    ClassTwo::onFinish(QNetworkReply *reply2){
    
         reply2->deleteLater();
    
    }
    

    The problem occours when I call the sendFile();
    The first slot onFinishValid execute TWO times then onFinish executes after.

    And the user see the message "Login fail" on screen... because the second reply is send to the first slot!

    I try change the name of var reply but nothing changes...

    What is wrong?

    My best regards and sorry for my bad english.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Are you using the same QNetworkAccessManager for both classes ?
    In any case, since you are only interested in reacting to the reply, why not connect only the reply finished signal rather than the QNetworkAccessManager ?



  • Hi SGaist, thank you!

    I'm using the same QNetworkAccessManager for both classes.
    And now, I removed connect(mpNetworkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinish(QNetworkReply*)));

    But nothing has changed.

    The slot onFinishValid() is called two times.

    The first time when
    networkMgr->post(request, datatoSend); //Check user
    is executed.

    And the second time when
    networkMgr->post(request, datatoSend); //Send file

    Then I have to create a new QNetworkAccessManager for the second class?

    My best regards!


    EDIT

    When I use different QNetworkAccessManager, it's works so fine.
    But I wonder if is not a grood pratice.

    Thanks.



  • @Helson said:

    connect(networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinishValid(QNetworkReply*)));

    By any chance whether above connect statement is called twice ? Can you try passing the Qt::UniqueConnection as 5th parameter to connect statement ?



  • You need to connect the finished signal of the QNetworkReply object instance returned by the QNetworkAccessManager::post() method, not the finished signal of the QNetworkAccessManager instance. That way the slots called are specific to the requests.

    Alternatively you can check the address of the QNetworkReply instance passed by the finished signal to see which request it belongs to.



  • @dheerendra I try to this, but not work :(
    Thank you.



  • @bsomervi Thanks for your explanation, but in terms of code, I don't know how I can achieve that...

    If you can explain me a little bit i'll be grateful.



  • Slot is called twice means that there are TWO connects executed. By looking your tries, you are making the multiple connects with two different objects.

    Either you are connecting the twice or creating two objects of ClassOne some how.

    Inside the slot use the sender() API to get which object is sending the signal. May be you can print the address of the object returned by the sender or try to use the object name. This will give the source of the problem.



  • class ClassOne {
        // ...
    private:
        // ...
        QNetworkReply * reply_ptr;
        // ...
    };
    
    void ClassOne::checkUser{
    // connect(networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinishValid(QNetworkReply*)));
    reply_ptr = networkMgr->post(request, datatoSend);
    connect(reply_ptr, &QNetworkReply::finished, this, &ClassOne::onFinshValid);
    
    void ClassOne::haveData() {
        QString data {reply_ptr->readAll()};
        ...
            if(true){
                 ...some code
             showMessage("Login OK! Sending file!")
             sendFile();
           } else{
               showMessage("Login fail")
            } 
             reply_ptr->deleteLater();
    }
    
    //Class 2
    class ClassTwo {
        // ...
    private:
        // ...
        QNetworkReply * reply_ptr;
        // ...
    };
    
    ClassTwo::sendFile(){
        // connect(mpNetworkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinish(QNetworkReply*)));  //Other slot
        reply_ptr = networkMgr->post(request, datatoSend);
        connect(reply_ptr, &QNetworkReply::finished, this, &ClassTwo::onFinish);
    }
    
    ClassTwo::onFinish(){
    
         reply_ptr->deleteLater();
    }
    


  • @bsomervi
    Hello again!

    When I try in this way the slot is never called:

    reply_ptr = networkMgr->post(request, datatoSend);
    connect(reply_ptr, &QNetworkReply::finished, this, &ClassTwo::onFinish)
    

    I try too

    connect(reply_ptr, &QNetworkReply::finished(), this, &ClassTwo::onFinish())
    

    and

    connect(reply_ptr, finished(QNetworkReply*), this, (onFinish(QNetworkReply*)))
    

    But nothing happen.

    What I'm doing wrong?


  • Lifetime Qt Champion

    Silly question: are you sure the request is sent ? You should also connect the error signal



  • Can you share the complete code for us to check ? It helps us to quickly help you.



  • void ClassOne::init(){
         mpNetworkMgr = new QNetworkAccessManager(this);
    }
    
    void ClassOne::sendFile(){
    
    	        QString data;
                QByteArray datatoSend;
    			
    			data = ...
    
    			datatoSend = data.toAscii();
    
    			webServHost = settings->addressWebServiceHost();
    			addressWebServUpload = settings->addressWebServiceUpload();	
                QNetworkRequest request(QUrl(QString(addressWebServUpload).toAscii().constData()));
    			
                request.setHeader(QNetworkRequest::ContentLengthHeader, datatoSend.size());
    			request.setRawHeader("SOAPAction","");
    			request.setRawHeader("...");
    
                // Send the file
                mpNetworkMgr->post(request, datatoSend);
            }
    	}
    }
    
    void ClassOne::validateUser(QString username, QString password){
    			
                QString data;
                QByteArray datatoSend;
    
    			data = "...";		
    				
                request.setHeader(QNetworkRequest::ContentLengthHeader, datatoSend.size());
    			request.setRawHeader("SOAPAction","");
    			request.setRawHeader("Content-Type", "text/xml; charset=UTF-8");					
    			request.setRawHeader("Host", webServHost.toAscii());
                request.setRawHeader("Accept", "*/*");
                request.setRawHeader("Accept-Language", "pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4");
    
    			connect(mpNetworkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinishedValidation(QNetworkReply*)));
                mpNetworkMgr->post(request, datatoSend);
    }
    
    void ClassOne::onFinishedValidation(QNetworkReply *reply){
     	QString data = (QString) reply->readAll();
    	QString result;
    	QXmlStreamReader xml(data);
    
    	reply->deleteLater();
    
    	while(!xml.atEnd()){
    	xml.readNextStartElement();
    		if(xml.name() == "test" && !xml.isEndElement()){
    			result = xml.readElementText();		
    		}
    	}
    
    	if(result == "true"){
    		UBApplication::showMessage(tr("Login OK"));
    		UBApplication::showMessage(tr("Sending FILE...!"));		
    		sendFile();
    	} else {
    		UBApplication::showMessage(tr("Failed to login"));
    	}    
    	reply->deleteLater();
    }
    
    void ClassOne::onFinished(QNetworkReply *reply2)
    { 	
    	reply2->deleteLater();
    }
    
    void ClassOne::publish()
    {
        UBPublicationLoginSigeuDlg dlg;
        if(QDialog::Accepted == dlg.exec())
        {
            mUsername = dlg.login();
            mPassword = dlg.password();
            validateUser(mUsername, mPassword);			
        }
    }
    
    
    
    ###############
    
    class ClassOne : public QObject
    {
        Q_OBJECT;
    
    public:
        explicit ClassOne();
        virtual ~ClassOne();
    
        void publish();
    	
    private slots:
    	void onFinished(QNetworkReply* reply2);
        void onFinishedValidation(QNetworkReply* reply);
    
    private:
        void init();
        void sendFile();
    	void validateUser(QString username, QString password);
       
        QNetworkAccessManager* mpNetworkMgr;
        QString mUsername;
        QString mPassword;
    	QString webServHost;
    
    
    };
    

    Then I call the publish() method.
    Remember, If I use a different "QNetworkAccessManager", the slot onFinishedValidation() executes only one time.

    My best regards.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.